2024-10-25 14:42:19 +02:00
#!/usr/bin/python3
2013-07-02 14:50:19 +02:00
# -*- coding: UTF-8 -*-
#
# Script for checking global health of host running VMware ESX/ESXi
#
# Licence : GNU General Public Licence (GPL) http://www.gnu.org/
# 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 2
# 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
2020-06-05 16:12:13 +02:00
# along with this program; if not, see <https://www.gnu.org/licenses/>.
2013-07-02 14:50:19 +02:00
#
# Pre-req : pywbem
#
# Copyright (c) 2008 David Ligeret
# Copyright (c) 2009 Joshua Daniel Franklin
# Copyright (c) 2010 Branden Schneider
2024-10-25 14:42:19 +02:00
# Copyright (c) 2010-2024 Claudio Kuenzler
2013-07-02 14:50:19 +02:00
# Copyright (c) 2010 Samir Ibradzic
# Copyright (c) 2010 Aaron Rogers
# Copyright (c) 2011 Ludovic Hutin
# Copyright (c) 2011 Carsten Schoene
# Copyright (c) 2011-2012 Phil Randal
# Copyright (c) 2011 Fredrik Aslund
# Copyright (c) 2011 Bertrand Jomin
# Copyright (c) 2011 Ian Chard
# Copyright (c) 2012 Craig Hart
2013-07-02 16:11:14 +02:00
# Copyright (c) 2013 Carl R. Friend
2015-01-19 16:48:38 +01:00
# Copyright (c) 2015 Andreas Gottwald
2015-07-10 09:56:25 +02:00
# Copyright (c) 2015 Stanislav German-Evtushenko
2015-11-11 08:57:05 +01:00
# Copyright (c) 2015 Stefan Roos
2018-04-11 07:35:09 +02:00
# Copyright (c) 2018 Peter Newman
2020-06-05 16:12:13 +02:00
# Copyright (c) 2020 Luca Berra
2022-07-08 06:49:52 +02:00
# Copyright (c) 2022 Marco Markgraf
2013-07-02 14:50:19 +02:00
#
2024-10-25 15:37:00 +02:00
# The VMware CIM API is documented here (as of October 2024):
# https://docs.vmware.com/en/VMware-vSphere/7.0/vsphere-cim-smash-server-management-api-programming-guide/GUID-2725D01E-AE02-4EF2-9E98-5AB82AA0349A.html
# The CIM classes are documented here (as of October 2024):
# https://vdc-download.vmware.com/vmwb-repository/dcr-public/27c1c014-7315-4d6b-8e6b-292130a79b3c/36aca268-99fa-4916-b993-a077de55cbf1/CIM_API_Reference/index.html
2013-07-02 14:50:19 +02:00
#
2019-05-10 10:00:50 +02:00
# This monitoring plugin is maintained and documented here:
# https://www.claudiokuenzler.com/monitoring-plugins/check_esxi_hardware.php
2013-07-02 14:50:19 +02:00
#
#@---------------------------------------------------
#@ History
#@---------------------------------------------------
#@ Date : 20080820
#@ Author : David Ligeret
#@ Reason : Initial release
#@---------------------------------------------------
#@ Date : 20080821
#@ Author : David Ligeret
#@ Reason : Add verbose mode
#@---------------------------------------------------
#@ Date : 20090219
#@ Author : Joshua Daniel Franklin
#@ Reason : Add try/except to catch AuthError and CIMError
#@---------------------------------------------------
#@ Date : 20100202
#@ Author : Branden Schneider
#@ Reason : Added HP Support (HealthState)
#@---------------------------------------------------
#@ Date : 20100512
#@ Author : Claudio Kuenzler www.claudiokuenzler.com
#@ Reason : Combined different versions (Joshua and Branden)
#@ Reason : Added hardware type switch (dell or hp)
#@---------------------------------------------------
#@ Date : 20100626/28
#@ Author : Samir Ibradzic www.brastel.com
#@ Reason : Added basic server info
#@ Reason : Wanted to have server name, serial number & bios version at output
#@ Reason : Set default return status to Unknown
#@---------------------------------------------------
#@ Date : 20100702
#@ Author : Aaron Rogers www.cloudmark.com
#@ Reason : GlobalStatus was incorrectly getting (re)set to OK with every CIM element check
#@---------------------------------------------------
#@ Date : 20100705
#@ Author : Claudio Kuenzler www.claudiokuenzler.com
#@ Reason : Due to change 20100702 all Dell servers would return UNKNOWN instead of OK...
#@ Reason : ... so added Aaron's logic at the end of the Dell checks as well
#@---------------------------------------------------
#@ Date : 20101028
#@ Author : Claudio Kuenzler www.claudiokuenzler.com
#@ Reason : Changed text in Usage and Example so people dont forget to use https://
#@---------------------------------------------------
#@ Date : 20110110
#@ Author : Ludovic Hutin (Idea and Coding) / Claudio Kuenzler (Bugfix)
#@ Reason : If Dell Blade Servers are used, Serial Number of Chassis was returned
#@---------------------------------------------------
#@ Date : 20110207
#@ Author : Carsten Schoene carsten.schoene.cc
#@ Reason : Bugfix for Intel systems (in this case Intel SE7520) - use 'intel' as system type
#@---------------------------------------------------
#@ Date : 20110215
#@ Author : Ludovic Hutin
#@ Reason : Plugin now catches Socket Error (Timeout Error) and added a timeout parameter
#@---------------------------------------------------
#@ Date : 20110217/18
#@ Author : Ludovic Hutin / Tom Murphy
#@ Reason : Bugfix in Socket Error if clause
#@---------------------------------------------------
#@ Date : 20110221
#@ Author : Claudio Kuenzler www.claudiokuenzler.com
#@ Reason : Remove recently added Timeout due to incompabatility on Windows
#@ Reason : and changed name of plugin to check_esxi_hardware
#@---------------------------------------------------
#@ Date : 20110426
#@ Author : Claudio Kuenzler www.claudiokuenzler.com
#@ Reason : Added 'ibm' hardware type (compatible to Dell output). Tested by Keith Erekson.
#@---------------------------------------------------
#@ Date : 20110426
#@ Author : Phil Randal
#@ Reason : URLise Dell model and tag numbers (as in check_openmanage)
#@ Reason : Return performance data (as in check_openmanage, using similar names where possible)
#@ Reason : Minor code tidyup - use elementName instead of instance['ElementName']
#@---------------------------------------------------
#@ Date : 20110428
#@ Author : Phil Randal (phil.randal@gmail.com)
#@ Reason : If hardware type is specified as 'auto' try to autodetect vendor
#@ Reason : Return performance data for some HP models
#@ Reason : Indent 'verbose' output to make it easier to read
#@ Reason : Use OptionParser to give better parameter parsing (retaining compatability with original)
#@---------------------------------------------------
#@ Date : 20110503
#@ Author : Phil Randal (phil.randal@gmail.com)
#@ Reason : Fix bug in HP Virtual Fan percentage output
#@ Reason : Slight code reorganisation
#@ Reason : Sort performance data
#@ Reason : Fix formatting of current output
#@---------------------------------------------------
#@ Date : 20110504
#@ Author : Phil Randal (phil.randal@gmail.com)
#@ Reason : Minor code changes and documentation improvements
#@ Reason : Remove redundant mismatched ' character in performance data output
#@ Reason : Output non-integral values for all sensors to fix problem seen with system board voltage sensors
#@ on an IBM server (thanks to Attilio Drei for the sample output)
#@---------------------------------------------------
#@ Date : 20110505
#@ Author : Fredrik Aslund
#@ Reason : Added possibility to use first line of a file as password (file:)
#@---------------------------------------------------
#@ Date : 20110505
#@ Author : Phil Randal (phil.randal@gmail.com)
#@ Reason : Simplfy 'verboseoutput' to use 'verbose' as global variable instead of as parameter
#@ Reason : Don't look at performance data from CIM_NumericSensor if we're not using it
#@ Reason : Add --no-power, --no-volts, --no-current, --no-temp, and --no-fan options
#@---------------------------------------------------
#@ Date : 20110506
#@ Author : Phil Randal (phil.randal@gmail.com)
#@ Reason : Reinstate timeouts with --timeout parameter (but not on Windows)
#@ Reason : Allow file:passwordfile in old-style arguments too
#@---------------------------------------------------
#@ Date : 20110507
#@ Author : Phil Randal (phil.randal@gmail.com)
#@ Reason : On error, include numeric sensor value in output
#@---------------------------------------------------
#@ Date : 20110520
#@ Author : Bertrand Jomin
#@ Reason : Plugin had problems to handle some S/N from IBM Blade Servers
#@---------------------------------------------------
#@ Date : 20110614
#@ Author : Claudio Kuenzler (www.claudiokuenzler.com)
#@ Reason : Rewrote file handling and file can now be used for user AND password
#@---------------------------------------------------
#@ Date : 20111003
#@ Author : Ian Chard (ian@chard.org)
#@ Reason : Allow a list of unwanted elements to be specified, which is useful
#@ in cases where hardware isn't well supported by ESXi
#@---------------------------------------------------
#@ Date : 20120402
#@ Author : Claudio Kuenzler (www.claudiokuenzler.com)
#@ Reason : Making plugin GPL compatible (Copyright) and preparing for OpenBSD port
#@---------------------------------------------------
#@ Date : 20120405
#@ Author : Phil Randal (phil.randal@gmail.com)
#@ Reason : Fix lookup of warranty info for Dell
#@---------------------------------------------------
#@ Date : 20120501
#@ Author : Craig Hart
#@ Reason : Bugfix in manufacturer discovery when cim entry not found or empty
#@---------------------------------------------------
#@ Date : 20121027
#@ Author : Claudio Kuenzler (www.claudiokuenzler.com)
#@ Reason : Added workaround for Dell PE x620 where "System Board 1 Riser Config Err 0: Connected"
#@ element outputs wrong return code. Dell, please fix that.
2015-06-10 12:47:12 +02:00
#@ Added web-link to VMware CIM API 5.x at top of script.
2013-07-02 14:50:19 +02:00
#@---------------------------------------------------
#@ Date : 20130424
#@ Author : Claudio Kuenzler (www.claudiokuenzler.com)
#@ Reason : Another workaround for Dell systems "System Board 1 LCD Cable Pres 0: Connected"
#@---------------------------------------------------
2013-07-02 16:11:14 +02:00
#@ Date : 20130702
#@ Author : Carl R. Friend
#@ Reason : Improving wrong authentication timeout and exit UNKNOWN
#@---------------------------------------------------
2013-07-25 15:07:15 +02:00
#@ Date : 20130725
#@ Author : Phil Randal (phil.randal@gmail.com)
#@ Reason : Fix lookup of warranty info for Dell
#@---------------------------------------------------
2014-03-19 09:49:37 +01:00
#@ Date : 20140319
#@ Author : Claudio Kuenzler (www.claudiokuenzler.com)
2014-03-19 10:14:08 +01:00
#@ Reason : Another two workarounds for Dell systems (VGA Cable Pres 0, Add-in Card 4 PEM Presence 0)
2014-03-19 09:49:37 +01:00
#@---------------------------------------------------
2015-01-09 11:56:17 +01:00
#@ Date : 20150109
2014-09-09 17:28:53 +02:00
#@ Author : Claudio Kuenzler (www.claudiokuenzler.com)
#@ Reason : Output serial number of chassis if a blade server is checked
#@---------------------------------------------------
2015-01-19 16:48:38 +01:00
#@ Date : 20150119
2015-01-15 15:13:47 +01:00
#@ Author : Andreas Gottwald
#@ Reason : Fix NoneType element bug
#@---------------------------------------------------
2015-06-26 14:30:42 +02:00
#@ Date : 20150626
2015-05-12 08:45:32 +02:00
#@ Author : Claudio Kuenzler (www.claudiokuenzler.com)
#@ Reason : Added support for patched pywbem 0.7.0 and new version 0.8.0, handle SSL error exception
#@---------------------------------------------------
2015-07-10 09:56:25 +02:00
#@ Date : 20150710
#@ Author : Stanislav German-Evtushenko
#@ Reason : Exit Unknown instead of Critical for timeouts and auth errors
#@---------------------------------------------------
2015-11-11 08:57:05 +01:00
#@ Date : 20151111
#@ Author : Stefan Roos
#@ Reason : Removed unused sensor_value variable and string import.
#@ Reason : Added global hosturl variable declaration after imports.
#@---------------------------------------------------
2016-04-11 15:19:37 +02:00
#@ Date : 20160411
#@ Author : Claudio Kuenzler (www.claudiokuenzler.com)
#@ Reason : Distinguish between pywbem 0.7 and 0.8 (which is now released)
#@---------------------------------------------------
2016-05-31 07:28:55 +02:00
#@ Date : 20160531
#@ Author : Claudio Kuenzler (www.claudiokuenzler.com)
#@ Reason : Add parameter for variable CIM port (useful when behind NAT)
#@---------------------------------------------------
2016-10-13 15:59:19 +02:00
#@ Date : 20161013
#@ Author : Claudio Kuenzler (www.claudiokuenzler.com)
#@ Reason : Added support for pywbem 0.9.x (and upcoming releases)
#@---------------------------------------------------
2017-09-05 21:06:53 +02:00
#@ Date : 20170905
#@ Author : Claudio Kuenzler (www.claudiokuenzler.com)
#@ Reason : Added option to ignore LCD/Display related elements (--no-lcd)
#@---------------------------------------------------
2018-03-29 09:15:07 +02:00
#@ Date : 20180329
#@ Author : Claudio Kuenzler (www.claudiokuenzler.com)
#@ Reason : Try to use internal pywbem function to determine version
#@---------------------------------------------------
2018-04-11 07:35:09 +02:00
#@ Date : 20180411
#@ Author : Peter Newman
#@ Reason : Throw an unknown if we can't fetch the data for some reason
#@---------------------------------------------------
2018-10-01 11:15:59 +02:00
#@ Date : 20181001
#@ Author : Claudio Kuenzler
#@ Reason : python3 compatibility
#@---------------------------------------------------
2019-05-10 10:00:50 +02:00
#@ Date : 20190510
#@ Author : Claudio Kuenzler
#@ Reason : Allow regular expressions from ignore list (-r)
#@---------------------------------------------------
2019-07-01 10:39:59 +02:00
#@ Date : 20190701
#@ Author : Phil Randal (phil.randal@gmail.com)
#@ Reason : Fix lookup of warranty info for Dell (again)
2020-06-05 10:18:51 +02:00
#@---------------------------------------------------
2020-06-05 16:12:13 +02:00
#@ Date : 20200605
2020-06-05 10:18:51 +02:00
#@ Author : Luca Berra
#@ Reason : Add option to ignore chassis intrusion (Supermicro)
2020-06-05 16:12:13 +02:00
#@---------------------------------------------------
#@ Date : 20200605
#@ Author : Claudio Kuenzler
#@ Reason : Add parameter (-S) for custom SSL/TLS protocol version
#@---------------------------------------------------
2020-07-10 07:30:43 +02:00
#@ Date : 20200710
#@ Author : Claudio Kuenzler
#@ Reason : Improve missing mandatory parameter error text (issue #47)
#@ Delete temporary openssl config file after use (issue #48)
#@---------------------------------------------------
2021-08-09 14:23:32 +02:00
#@ Date : 20210809
#@ Author : Claudio Kuenzler
#@ Reason : Fix TLSv1 usage (issue #51)
#@---------------------------------------------------
2022-07-08 06:44:09 +02:00
#@ Date : 20220509
#@ Author : Marco Markgraf
2022-07-08 06:49:52 +02:00
#@ Reason : Added JSON-output (Zabbix needs it)
2022-07-08 06:44:09 +02:00
#@---------------------------------------------------
2022-12-30 08:57:39 +01:00
#@ Date : 20221230
#@ Author : Claudio Kuenzler
#@ Reason : Fix bug when missing S/N (issue #68)
#@---------------------------------------------------
2024-10-25 14:42:19 +02:00
#@ Date : 20241025
#@ Author : Claudio Kuenzler
#@ Reason : Fix pkg_resources deprecation warning
# Remove python2 compatibility
# Remove pywbem 0.7.0 compatibility
#@---------------------------------------------------
2013-07-02 14:50:19 +02:00
import sys
import time
import pywbem
import re
2022-07-08 06:44:09 +02:00
import json
2013-07-02 14:50:19 +02:00
from optparse import OptionParser , OptionGroup
2024-10-25 14:42:19 +02:00
version = ' 20241025 '
2013-07-02 14:50:19 +02:00
NS = ' root/cimv2 '
2016-04-07 09:11:40 +02:00
hosturl = ' '
2013-07-02 14:50:19 +02:00
# define classes to check 'OperationStatus' instance
ClassesToCheck = [
' OMC_SMASHFirmwareIdentity ' ,
' CIM_Chassis ' ,
' CIM_Card ' ,
' CIM_ComputerSystem ' ,
' CIM_NumericSensor ' ,
' CIM_Memory ' ,
' CIM_Processor ' ,
' CIM_RecordLog ' ,
' OMC_DiscreteSensor ' ,
' OMC_Fan ' ,
' OMC_PowerSupply ' ,
' VMware_StorageExtent ' ,
' VMware_Controller ' ,
' VMware_StorageVolume ' ,
' VMware_Battery ' ,
' VMware_SASSATAPort '
]
sensor_Type = {
0 : ' unknown ' ,
1 : ' Other ' ,
2 : ' Temperature ' ,
3 : ' Voltage ' ,
4 : ' Current ' ,
5 : ' Tachometer ' ,
6 : ' Counter ' ,
7 : ' Switch ' ,
8 : ' Lock ' ,
9 : ' Humidity ' ,
10 : ' Smoke Detection ' ,
11 : ' Presence ' ,
12 : ' Air Flow ' ,
13 : ' Power Consumption ' ,
14 : ' Power Production ' ,
15 : ' Pressure ' ,
16 : ' Intrusion ' ,
32768 : ' DMTF Reserved ' ,
65535 : ' Vendor Reserved '
}
data = [ ]
2022-07-08 06:44:09 +02:00
xdata = { }
2013-07-02 14:50:19 +02:00
perf_Prefix = {
1 : ' Pow ' ,
2 : ' Vol ' ,
3 : ' Cur ' ,
4 : ' Tem ' ,
5 : ' Fan ' ,
6 : ' FanP '
}
# parameters
# host name
hostname = ' '
2016-04-14 21:41:31 +02:00
# cim port
cimport = ' '
2013-07-02 14:50:19 +02:00
# user
user = ' '
# password
password = ' '
# vendor - possible values are 'unknown', 'auto', 'dell', 'hp', 'ibm', 'intel'
vendor = ' unknown '
# verbose
verbose = False
2022-07-08 06:44:09 +02:00
# output json
format = ' string '
pretty = False
2013-07-02 14:50:19 +02:00
# Produce performance data output for nagios
perfdata = False
# timeout
timeout = 0
# elements to ignore (full SEL, broken BIOS, etc)
ignore_list = [ ]
2019-05-10 10:00:50 +02:00
regex_ignore_list = [ ]
regex = False
2013-07-02 14:50:19 +02:00
# urlise model and tag numbers (currently only Dell supported, but the code does the right thing for other vendors)
urlise_country = ' '
# collect perfdata for each category
get_power = True
get_volts = True
get_current = True
get_temp = True
get_fan = True
2017-08-31 21:19:34 +02:00
get_lcd = True
2020-06-05 10:18:51 +02:00
get_intrusion = True
2013-07-02 14:50:19 +02:00
# define exit codes
ExitOK = 0
ExitWarning = 1
ExitCritical = 2
ExitUnknown = 3
2014-09-16 13:27:48 +02:00
# Special handling for blade servers
isblade = " no "
2013-07-25 15:07:15 +02:00
def dell_country ( country ) :
if country == ' at ' : # Austria
return ' at/de/ '
if country == ' be ' : # Belgium
return ' be/nl/ '
if country == ' cz ' : # Czech Republic
return ' cz/cs/ '
if country == ' de ' : # Germany
return ' de/de/ '
if country == ' dk ' : # Denmark
return ' dk/da/ '
if country == ' es ' : # Spain
return ' es/es/ '
if country == ' fi ' : # Finland
return ' fi/fi/ '
if country == ' fr ' : # France
return ' fr/fr/ '
if country == ' gr ' : # Greece
return ' gr/en/ '
if country == ' it ' : # Italy
return ' it/it/ '
if country == ' il ' : # Israel
return ' il/en/ '
if country == ' me ' : # Middle East
return ' me/en/ '
if country == ' no ' : # Norway
return ' no/no/ '
if country == ' nl ' : # The Netherlands
return ' nl/nl/ '
if country == ' pl ' : # Poland
return ' pl/pl/ '
if country == ' pt ' : # Portugal
return ' pt/en/ '
if country == ' ru ' : # Russia
return ' ru/ru/ '
if country == ' se ' : # Sweden
return ' se/sv/ '
if country == ' uk ' : # United Kingdom
return ' uk/en/ '
if country == ' za ' : # South Africa
return ' za/en/ '
if country == ' br ' : # Brazil
return ' br/pt/ '
if country == ' ca ' : # Canada
return ' ca/en/ '
if country == ' mx ' : # Mexico
return ' mx/es/ '
if country == ' us ' : # United States
return ' us/en/ '
if country == ' au ' : # Australia
return ' au/en/ '
if country == ' cn ' : # China
return ' cn/zh/ '
if country == ' in ' : # India
return ' in/en/ '
# default
return ' en/us/ '
2013-07-02 14:50:19 +02:00
def urlised_server_info ( vendor , country , server_info ) :
#server_inf = server_info
if vendor == ' dell ' :
# Dell support URLs (idea and tables borrowed from check_openmanage)
2019-07-01 10:39:59 +02:00
du = ' http://www.dell.com/support/home/ ' + dell_country ( country ) + ' 04/product-support/product/poweredge- '
2013-07-02 14:50:19 +02:00
if ( server_info is not None ) :
p = re . match ( ' (.*)PowerEdge (.*) (.*) ' , server_info )
if ( p is not None ) :
2013-07-25 15:27:46 +02:00
md = p . group ( 2 )
2013-07-25 15:26:38 +02:00
if md == ' R210 II ' :
2013-07-25 15:07:15 +02:00
md = ' r210-2 '
2013-07-25 15:26:38 +02:00
md = md . lower ( )
2019-07-01 10:39:59 +02:00
server_info = p . group ( 1 ) + ' <a href= " ' + du + md + ' / " >PowerEdge ' + p . group ( 2 ) + ' </a> ' + p . group ( 3 )
2013-07-02 14:50:19 +02:00
elif vendor == ' hp ' :
return server_info
elif vendor == ' ibm ' :
return server_info
elif vendor == ' intel ' :
return server_info
return server_info
# ----------------------------------------------------------------------
def system_tag_url ( vendor , country ) :
if vendor == ' dell ' :
# Dell support sites
2019-07-01 10:39:59 +02:00
supportsite = ' http://www.dell.com/support/home/ '
dellsuffix = ' 19/product-support/servicetag/ '
2013-07-02 14:50:19 +02:00
# warranty URLs for different country codes
2013-07-25 15:07:15 +02:00
return supportsite + dell_country ( country ) + dellsuffix
2013-07-02 14:50:19 +02:00
# elif vendor == 'hp':
# elif vendor == 'ibm':
# elif vendor == 'intel':
2013-07-25 15:07:15 +02:00
return ' '
2013-07-02 14:50:19 +02:00
# ----------------------------------------------------------------------
def urlised_serialnumber ( vendor , country , SerialNumber ) :
if SerialNumber is not None :
tu = system_tag_url ( vendor , country )
if tu != ' ' :
SerialNumber = ' <a href= " ' + tu + SerialNumber + ' " > ' + SerialNumber + ' </a> '
return SerialNumber
# ----------------------------------------------------------------------
def verboseoutput ( message ) :
if verbose :
2018-10-01 11:15:59 +02:00
print ( time . strftime ( " % Y % m %d % H: % M: % S " ) , message )
2013-07-02 14:50:19 +02:00
# ----------------------------------------------------------------------
2022-07-08 06:44:09 +02:00
def xdataprint ( ) :
if format == ' json ' and not pretty :
print ( json . dumps ( xdata , sort_keys = True ) )
if format == ' json ' and pretty :
print ( json . dumps ( xdata , sort_keys = True , indent = 4 ) )
# ----------------------------------------------------------------------
2013-07-02 14:50:19 +02:00
def getopts ( ) :
2022-07-08 06:44:09 +02:00
global hosturl , hostname , cimport , sslproto , user , password , vendor , verbose , perfdata , urlise_country , timeout , ignore_list , regex , get_power , get_volts , get_current , get_temp , get_fan , get_lcd , get_intrusion , format , pretty
2020-06-05 16:12:13 +02:00
usage = " usage: % prog -H hostname -U username -P password [-C port -S proto -V vendor -v -p -I XX -i list,list -r] \n " \
2019-05-10 10:00:50 +02:00
" example: % prog -H hostname -U root -P password -C 5989 -V auto -I uk \n \n " \
2013-07-02 14:50:19 +02:00
" or, verbosely: \n \n " \
2022-07-08 06:44:09 +02:00
" usage: % prog --host=hostname --user=username --pass=password [--cimport=port --sslproto=version --vendor=system --verbose --perfdata --html=XX --format=json --pretty] \n "
2013-07-02 14:50:19 +02:00
parser = OptionParser ( usage = usage , version = " % prog " + version )
group1 = OptionGroup ( parser , ' Mandatory parameters ' )
group2 = OptionGroup ( parser , ' Optional parameters ' )
2020-06-05 16:12:13 +02:00
group1 . add_option ( " -H " , " --host " , dest = " host " , help = " connect to HOST " , metavar = " HOST " )
2013-07-02 14:50:19 +02:00
group1 . add_option ( " -U " , " --user " , dest = " user " , help = " user to connect as " , metavar = " USER " )
group1 . add_option ( " -P " , " --pass " , dest = " password " , \
help = " password, if password matches file:<path>, first line of given file will be used as password " , metavar = " PASS " )
2016-04-14 21:41:31 +02:00
group2 . add_option ( " -C " , " --cimport " , dest = " cimport " , help = " CIM port (default 5989) " , metavar = " CIMPORT " )
2021-08-09 14:23:32 +02:00
group2 . add_option ( " -S " , " --sslproto " , dest = " sslproto " , help = " SSL/TLS protocol version to overwrite system default: SSLv2, SSLv3, TLSv1, TLSv1.1, TLSv1.2, TLSv1.3 " , metavar = " SSLPROTO " )
2013-07-02 14:50:19 +02:00
group2 . add_option ( " -V " , " --vendor " , dest = " vendor " , help = " Vendor code: auto, dell, hp, ibm, intel, or unknown (default) " , \
metavar = " VENDOR " , type = ' choice ' , choices = [ ' auto ' , ' dell ' , ' hp ' , ' ibm ' , ' intel ' , ' unknown ' ] , default = " unknown " )
group2 . add_option ( " -v " , " --verbose " , action = " store_true " , dest = " verbose " , default = False , \
help = " print status messages to stdout (default is to be quiet) " )
group2 . add_option ( " -p " , " --perfdata " , action = " store_true " , dest = " perfdata " , default = False , \
help = " collect performance data for pnp4nagios (default is not to) " )
group2 . add_option ( " -I " , " --html " , dest = " urlise_country " , default = " " , \
help = " generate html links for country XX (default is not to) " , metavar = " XX " )
group2 . add_option ( " -t " , " --timeout " , action = " store " , type = " int " , dest = " timeout " , default = 0 , \
help = " timeout in seconds - no effect on Windows (default = no timeout) " )
group2 . add_option ( " -i " , " --ignore " , action = " store " , type = " string " , dest = " ignore " , default = " " , \
help = " comma-separated list of elements to ignore " )
2019-05-10 10:00:50 +02:00
group2 . add_option ( " -r " , " --regex " , action = " store_true " , dest = " regex " , default = False , \
help = " allow regular expression lookup of ignore list " )
2013-07-02 14:50:19 +02:00
group2 . add_option ( " --no-power " , action = " store_false " , dest = " get_power " , default = True , \
help = " don ' t collect power performance data " )
group2 . add_option ( " --no-volts " , action = " store_false " , dest = " get_volts " , default = True , \
help = " don ' t collect voltage performance data " )
group2 . add_option ( " --no-current " , action = " store_false " , dest = " get_current " , default = True , \
help = " don ' t collect current performance data " )
group2 . add_option ( " --no-temp " , action = " store_false " , dest = " get_temp " , default = True , \
help = " don ' t collect temperature performance data " )
group2 . add_option ( " --no-fan " , action = " store_false " , dest = " get_fan " , default = True , \
help = " don ' t collect fan performance data " )
2017-08-31 21:19:34 +02:00
group2 . add_option ( " --no-lcd " , action = " store_false " , dest = " get_lcd " , default = True , \
help = " don ' t collect lcd/front display status " )
2020-06-05 10:18:51 +02:00
group2 . add_option ( " --no-intrusion " , action = " store_false " , dest = " get_intrusion " , default = True , \
help = " don ' t collect chassis intrusion status " )
2022-07-08 06:44:09 +02:00
group2 . add_option ( " --format " , dest = " format " , help = " ' string ' (default) or ' json ' " , \
metavar = " FORMAT " , type = ' choice ' , choices = [ ' string ' , ' json ' ] , default = " string " )
group2 . add_option ( " --pretty " , action = " store_true " , dest = " pretty " , default = False , \
help = " return data as a pretty-printed json-array " )
2013-07-02 14:50:19 +02:00
parser . add_option_group ( group1 )
parser . add_option_group ( group2 )
# check input arguments
if len ( sys . argv ) < 2 :
2018-10-01 11:15:59 +02:00
print ( " no parameters specified \n " )
2013-07-02 14:50:19 +02:00
parser . print_help ( )
sys . exit ( - 1 )
# if first argument starts with 'https://' we have old-style parameters, so handle in old way
if re . match ( " https:// " , sys . argv [ 1 ] ) :
# check input arguments
if len ( sys . argv ) < 5 :
2018-10-01 11:15:59 +02:00
print ( " too few parameters \n " )
2013-07-02 14:50:19 +02:00
parser . print_help ( )
sys . exit ( - 1 )
if len ( sys . argv ) > 5 :
if sys . argv [ 5 ] == " verbose " :
verbose = True
hosturl = sys . argv [ 1 ]
user = sys . argv [ 2 ]
password = sys . argv [ 3 ]
vendor = sys . argv [ 4 ]
else :
# we're dealing with new-style parameters, so go get them!
( options , args ) = parser . parse_args ( )
# Making sure all mandatory options appeared.
mandatories = [ ' host ' , ' user ' , ' password ' ]
for m in mandatories :
if not options . __dict__ [ m ] :
2020-07-10 07:30:43 +02:00
print ( " mandatory option ' " + m + " ' not defined. read usage in help. \n " )
2013-07-02 14:50:19 +02:00
parser . print_help ( )
sys . exit ( - 1 )
hostname = options . host . lower ( )
# if user has put "https://" in front of hostname out of habit, do the right thing
# hosturl will end up as https://hostname
if re . match ( ' ^https:// ' , hostname ) :
hosturl = hostname
else :
hosturl = ' https:// ' + hostname
user = options . user
password = options . password
2016-04-14 21:41:31 +02:00
cimport = options . cimport
2022-07-08 06:44:09 +02:00
ignore_list = options . ignore . split ( ' , ' )
format = options . format
pretty = options . pretty
perfdata = options . perfdata
regex = options . regex
2020-06-05 16:12:13 +02:00
sslproto = options . sslproto
2022-07-08 06:44:09 +02:00
timeout = options . timeout
urlise_country = options . urlise_country . lower ( )
2013-07-02 14:50:19 +02:00
vendor = options . vendor . lower ( )
verbose = options . verbose
get_power = options . get_power
get_volts = options . get_volts
get_current = options . get_current
get_temp = options . get_temp
get_fan = options . get_fan
2017-08-31 21:19:34 +02:00
get_lcd = options . get_lcd
2020-06-05 10:18:51 +02:00
get_intrusion = options . get_intrusion
2013-07-02 14:50:19 +02:00
# if user or password starts with 'file:', use the first string in file as user, second as password
if ( re . match ( ' ^file: ' , user ) or re . match ( ' ^file: ' , password ) ) :
if re . match ( ' ^file: ' , user ) :
filextract = re . sub ( ' ^file: ' , ' ' , user )
filename = open ( filextract , ' r ' )
filetext = filename . readline ( ) . split ( )
user = filetext [ 0 ]
password = filetext [ 1 ]
filename . close ( )
elif re . match ( ' ^file: ' , password ) :
filextract = re . sub ( ' ^file: ' , ' ' , password )
filename = open ( filextract , ' r ' )
filetext = filename . readline ( ) . split ( )
password = filetext [ 0 ]
filename . close ( )
# ----------------------------------------------------------------------
getopts ( )
# if running on Windows, don't use timeouts and signal.alarm
on_windows = True
os_platform = sys . platform
if os_platform != " win32 " :
on_windows = False
import signal
def handler ( signum , frame ) :
2018-10-01 11:15:59 +02:00
print ( ' UNKNOWN: Execution time too long! ' )
2015-06-01 18:52:59 +02:00
sys . exit ( ExitUnknown )
2013-07-02 14:50:19 +02:00
2020-06-05 16:12:13 +02:00
# Use non-default CIM port
2016-04-14 21:41:31 +02:00
if cimport :
verboseoutput ( " Using manually defined CIM port " + cimport )
2022-07-08 06:44:09 +02:00
hosturl + = ' : ' + cimport
2020-06-05 16:12:13 +02:00
# Use non-default SSL protocol version
if sslproto :
verboseoutput ( " Using non-default SSL protocol: " + sslproto )
2021-08-09 14:23:32 +02:00
allowed_protos = [ " SSLv2 " , " SSLv3 " , " TLSv1 " , " TLSv1.1 " , " TLSv1.2 " , " TLSv1.3 " ]
2020-06-05 16:12:13 +02:00
if any ( proto . lower ( ) == sslproto . lower ( ) for proto in allowed_protos ) :
import os
sslconfpath = ' /tmp/ ' + hostname + ' _openssl.conf '
verboseoutput ( " Creating OpenSSL config file: " + sslconfpath )
try :
with open ( sslconfpath , ' w ' ) as config_file :
config_file . write ( " openssl_conf = openssl_init \n [openssl_init] \n ssl_conf = ssl_configuration \n [ssl_configuration] \n system_default = tls_system_default \n [tls_system_default] \n MinProtocol = " + sslproto + " \n " )
except Exception as e :
print ( ' CRITICAL: An error occured while trying to write ssl config file: %s ( %s ) ' % ( sslconfpath , e ) )
sys . exit ( ExitCritical )
os . environ [ " OPENSSL_CONF " ] = sslconfpath
else :
print ( ' CRITICAL: Invalid SSL protocol version given! ' )
sys . exit ( ExitCritical )
2017-09-02 11:24:37 +02:00
# Append lcd related elements to ignore list if --no-lcd was used
verboseoutput ( " LCD Status: %s " % get_lcd )
if not get_lcd :
ignore_list . append ( " System Board 1 LCD Cable Pres 0: Connected " )
ignore_list . append ( " System Board 1 VGA Cable Pres 0: Connected " )
ignore_list . append ( " Front Panel Board 1 FP LCD Cable 0: Connected " )
2017-09-05 21:06:53 +02:00
ignore_list . append ( " Front Panel Board 1 FP LCD Cable 0: Config Error " )
2016-04-14 21:41:31 +02:00
2020-06-05 10:18:51 +02:00
# Append chassis intrusion related elements to ignore list if --no-intrusion was used
verboseoutput ( " Chassis Intrusion Status: %s " % get_intrusion )
if not get_intrusion :
ignore_list . append ( " System Chassis 1 Chassis Intru: General Chassis intrusion " )
ignore_list . append ( " System Chassis 1 Chassis Intru: Drive Bay intrusion " )
ignore_list . append ( " System Chassis 1 Chassis Intru: I/O Card area intrusion " )
ignore_list . append ( " System Chassis 1 Chassis Intru: Processor area intrusion " )
ignore_list . append ( " System Chassis 1 Chassis Intru: System unplugged from LAN " )
ignore_list . append ( " System Chassis 1 Chassis Intru: Unauthorized dock " )
ignore_list . append ( " System Chassis 1 Chassis Intru: FAN area intrusion " )
ignore_list . append ( " System Chassis 1 Chassis Intru: Unknown " )
2013-07-02 14:50:19 +02:00
# connection to host
2024-10-25 14:42:19 +02:00
pywbemversion = pywbem . __version__
2015-06-10 12:47:12 +02:00
verboseoutput ( " Found pywbem version " + pywbemversion )
2024-10-25 14:42:19 +02:00
verboseoutput ( " Connection to " + hosturl )
wbemclient = pywbem . WBEMConnection ( hosturl , ( user , password ) , NS , no_verification = True )
2015-06-10 12:47:12 +02:00
2013-07-02 14:50:19 +02:00
# Add a timeout for the script. When using with Nagios, the Nagios timeout cannot be < than plugin timeout.
if on_windows == False and timeout > 0 :
signal . signal ( signal . SIGALRM , handler )
signal . alarm ( timeout )
# run the check for each defined class
GlobalStatus = ExitUnknown
server_info = " "
bios_info = " "
SerialNumber = " "
ExitMsg = " "
# if vendor is specified as 'auto', try to get vendor from CIM
# note: the default vendor is 'unknown'
if vendor == ' auto ' :
2013-07-02 16:11:14 +02:00
try :
c = wbemclient . EnumerateInstances ( ' CIM_Chassis ' )
2018-10-01 11:15:59 +02:00
except pywbem . cim_operations . CIMError as args :
2013-07-02 16:11:14 +02:00
if ( args [ 1 ] . find ( ' Socket error ' ) > = 0 ) :
2018-10-01 11:15:59 +02:00
print ( " UNKNOWN: {} " . format ( args ) )
2013-07-02 16:11:14 +02:00
sys . exit ( ExitUnknown )
2017-01-24 18:57:28 +01:00
elif ( args [ 1 ] . find ( ' ThreadPool --- Failed to enqueue request ' ) > = 0 ) :
2018-10-01 11:15:59 +02:00
print ( " UNKNOWN: {} " . format ( args ) )
2017-01-25 11:48:19 +01:00
sys . exit ( ExitUnknown )
2013-07-02 16:11:14 +02:00
else :
verboseoutput ( " Unknown CIM Error: %s " % args )
2020-06-05 16:12:13 +02:00
except pywbem . _exceptions . ConnectionError as args :
GlobalStatus = ExitUnknown
print ( " UNKNOWN: {} " . format ( args ) )
sys . exit ( GlobalStatus )
2018-10-01 11:15:59 +02:00
except pywbem . cim_http . AuthError as arg :
2013-07-02 16:11:14 +02:00
verboseoutput ( " Global exit set to UNKNOWN " )
GlobalStatus = ExitUnknown
2018-10-01 11:15:59 +02:00
print ( " UNKNOWN: Authentication Error " )
2013-07-02 16:11:14 +02:00
sys . exit ( GlobalStatus )
2013-07-02 14:50:19 +02:00
else :
2013-07-02 16:11:14 +02:00
man = c [ 0 ] [ u ' Manufacturer ' ]
if re . match ( " Dell " , man ) :
vendor = " dell "
elif re . match ( " HP " , man ) :
vendor = " hp "
elif re . match ( " IBM " , man ) :
vendor = " ibm "
elif re . match ( " Intel " , man ) :
vendor = " intel "
else :
vendor = ' unknown '
2013-07-02 14:50:19 +02:00
for classe in ClassesToCheck :
verboseoutput ( " Check classe " + classe )
try :
instance_list = wbemclient . EnumerateInstances ( classe )
2022-07-08 06:44:09 +02:00
except pywbem . _cim_operations . CIMError as args :
2013-07-02 14:50:19 +02:00
if ( args [ 1 ] . find ( ' Socket error ' ) > = 0 ) :
2018-10-01 11:15:59 +02:00
print ( " UNKNOWN: {} " . format ( args ) )
2015-03-16 13:16:47 +01:00
sys . exit ( ExitUnknown )
2017-01-25 11:48:19 +01:00
elif ( args [ 1 ] . find ( ' ThreadPool --- Failed to enqueue request ' ) > = 0 ) :
2018-10-01 11:15:59 +02:00
print ( " UNKNOWN: {} " . format ( args ) )
2017-01-25 11:48:19 +01:00
sys . exit ( ExitUnknown )
2013-07-02 14:50:19 +02:00
else :
verboseoutput ( " Unknown CIM Error: %s " % args )
2020-06-05 16:12:13 +02:00
except pywbem . _exceptions . ConnectionError as args :
GlobalStatus = ExitUnknown
print ( " UNKNOWN: {} " . format ( args ) )
sys . exit ( GlobalStatus )
2022-07-08 06:44:09 +02:00
except pywbem . _cim_http . AuthError as arg :
2013-07-02 16:11:14 +02:00
verboseoutput ( " Global exit set to UNKNOWN " )
2015-03-16 13:16:47 +01:00
GlobalStatus = ExitUnknown
2018-10-01 11:15:59 +02:00
print ( " UNKNOWN: Authentication Error " )
2013-07-02 16:11:14 +02:00
sys . exit ( GlobalStatus )
2013-07-02 14:50:19 +02:00
else :
# GlobalStatus = ExitOK #ARR
for instance in instance_list :
elementName = instance [ ' ElementName ' ]
2015-01-15 15:13:47 +01:00
if elementName is None :
2015-06-10 12:47:12 +02:00
elementName = ' Unknown '
2013-07-02 14:50:19 +02:00
elementNameValue = elementName
verboseoutput ( " Element Name = " + elementName )
# Ignore element if we don't want it
2019-05-10 10:00:50 +02:00
if ( regex == True ) and ( len ( ignore_list ) > 0 ) :
for ignore in ignore_list :
if re . search ( ignore , elementName , re . IGNORECASE ) :
verboseoutput ( " (ignored through regex) " )
regex_ignore_list . append ( elementName )
if ( elementName in ignore_list ) or ( elementName in regex_ignore_list ) :
2013-07-02 14:50:19 +02:00
verboseoutput ( " (ignored) " )
2018-04-10 15:37:18 +02:00
continue
2013-07-02 14:50:19 +02:00
# BIOS & Server info
if elementName == ' System BIOS ' :
bios_info = instance [ u ' Name ' ] + ' : ' \
+ instance [ u ' VersionString ' ] + ' ' \
+ str ( instance [ u ' ReleaseDate ' ] . datetime . date ( ) )
verboseoutput ( " VersionString = " + instance [ u ' VersionString ' ] )
2022-07-08 06:44:09 +02:00
xdata [ ' Bios Info ' ] = bios_info
2013-07-02 14:50:19 +02:00
elif elementName == ' Chassis ' :
man = instance [ u ' Manufacturer ' ]
if man is None :
man = ' Unknown Manufacturer '
verboseoutput ( " Manufacturer = " + man )
SerialNumber = instance [ u ' SerialNumber ' ]
2014-09-09 17:28:53 +02:00
SerialChassis = instance [ u ' SerialNumber ' ]
2013-07-02 14:50:19 +02:00
if SerialNumber :
verboseoutput ( " SerialNumber = " + SerialNumber )
server_info = man + ' '
if vendor != ' intel ' :
model = instance [ u ' Model ' ]
if model :
verboseoutput ( " Model = " + model )
2022-07-08 06:44:09 +02:00
server_info + = model
2013-07-02 14:50:19 +02:00
elif elementName == ' Server Blade ' :
SerialNumber = instance [ u ' SerialNumber ' ]
if SerialNumber :
verboseoutput ( " SerialNumber = " + SerialNumber )
2014-09-09 17:30:55 +02:00
isblade = " yes "
2013-07-02 14:50:19 +02:00
2022-07-08 06:44:09 +02:00
xdata [ ' SerialNumber ' ] = SerialNumber
2013-07-02 14:50:19 +02:00
# Report detail of Numeric Sensors and generate nagios perfdata
if classe == " CIM_NumericSensor " :
sensorType = instance [ u ' sensorType ' ]
sensStr = sensor_Type . get ( sensorType , " Unknown " )
if sensorType :
verboseoutput ( " sensorType = %d - %s " % ( sensorType , sensStr ) )
units = instance [ u ' BaseUnits ' ]
if units :
verboseoutput ( " BaseUnits = %d " % units )
# grab some of these values for Nagios performance data
scale = 10 * * instance [ u ' UnitModifier ' ]
verboseoutput ( " Scaled by = %f " % scale )
cr = int ( instance [ u ' CurrentReading ' ] ) * scale
verboseoutput ( " Current Reading = %f " % cr )
elementNameValue = " %s : %g " % ( elementName , cr )
ltnc = 0
utnc = 0
ltc = 0
utc = 0
if instance [ u ' LowerThresholdNonCritical ' ] is not None :
ltnc = instance [ u ' LowerThresholdNonCritical ' ] * scale
verboseoutput ( " Lower Threshold Non Critical = %f " % ltnc )
if instance [ u ' UpperThresholdNonCritical ' ] is not None :
utnc = instance [ u ' UpperThresholdNonCritical ' ] * scale
verboseoutput ( " Upper Threshold Non Critical = %f " % utnc )
if instance [ u ' LowerThresholdCritical ' ] is not None :
ltc = instance [ u ' LowerThresholdCritical ' ] * scale
verboseoutput ( " Lower Threshold Critical = %f " % ltc )
if instance [ u ' UpperThresholdCritical ' ] is not None :
utc = instance [ u ' UpperThresholdCritical ' ] * scale
verboseoutput ( " Upper Threshold Critical = %f " % utc )
#
if perfdata :
perf_el = elementName . replace ( ' ' , ' _ ' )
# Power and Current
if sensorType == 4 : # Current or Power Consumption
if units == 7 : # Watts
if get_power :
data . append ( ( " %s = %g ; %g ; %g " % ( perf_el , cr , utnc , utc ) , 1 ) )
2022-07-08 06:44:09 +02:00
xdata [ perf_el ] = { ' Unit ' : ' Watt ' , ' Value ' : cr , ' warn ' : utnc , ' crit ' : utc }
2013-07-02 14:50:19 +02:00
elif units == 6 : # Current
if get_current :
data . append ( ( " %s = %g ; %g ; %g " % ( perf_el , cr , utnc , utc ) , 3 ) )
2022-07-08 06:44:09 +02:00
xdata [ perf_el ] = { ' Unit ' : ' Ampere ' , ' Value ' : cr , ' warn ' : utnc , ' crit ' : utc }
2013-07-02 14:50:19 +02:00
# PSU Voltage
elif sensorType == 3 : # Voltage
if get_volts :
data . append ( ( " %s = %g ; %g ; %g " % ( perf_el , cr , utnc , utc ) , 2 ) )
2022-07-08 06:44:09 +02:00
xdata [ perf_el ] = { ' Unit ' : ' Volt ' , ' Value ' : cr , ' warn ' : utnc , ' crit ' : utc }
2013-07-02 14:50:19 +02:00
# Temperatures
elif sensorType == 2 : # Temperature
if get_temp :
data . append ( ( " %s = %g ; %g ; %g " % ( perf_el , cr , utnc , utc ) , 4 ) )
2022-07-08 06:44:09 +02:00
xdata [ perf_el ] = { ' Value ' : cr , ' warn ' : utnc , ' crit ' : utc }
2013-07-02 14:50:19 +02:00
# Fan speeds
elif sensorType == 5 : # Tachometer
if get_fan :
2022-07-08 06:44:09 +02:00
if units == 65 : # percentage
2013-07-02 14:50:19 +02:00
data . append ( ( " %s = %g %% ; %g ; %g " % ( perf_el , cr , utnc , utc ) , 6 ) )
2022-07-08 06:44:09 +02:00
xdata [ perf_el ] = { ' Unit ' : ' % ' , ' Value ' : cr , ' warn ' : utnc , ' crit ' : utc }
2013-07-02 14:50:19 +02:00
else :
data . append ( ( " %s = %g ; %g ; %g " % ( perf_el , cr , utnc , utc ) , 5 ) )
2022-07-08 06:44:09 +02:00
xdata [ perf_el ] = { ' Value ' : cr , ' warn ' : utnc , ' crit ' : utc }
2013-07-02 14:50:19 +02:00
elif classe == " CIM_Processor " :
verboseoutput ( " Family = %d " % instance [ ' Family ' ] )
verboseoutput ( " CurrentClockSpeed = %d MHz " % instance [ ' CurrentClockSpeed ' ] )
# HP Check
if vendor == " hp " :
if instance [ ' HealthState ' ] is not None :
elementStatus = instance [ ' HealthState ' ]
verboseoutput ( " Element HealthState = %d " % elementStatus )
interpretStatus = {
0 : ExitOK , # Unknown
5 : ExitOK , # OK
10 : ExitWarning , # Degraded
15 : ExitWarning , # Minor
20 : ExitCritical , # Major
25 : ExitCritical , # Critical
30 : ExitCritical , # Non-recoverable Error
} [ elementStatus ]
if ( interpretStatus == ExitCritical ) :
2017-01-24 19:06:35 +01:00
verboseoutput ( " Global exit set to CRITICAL " )
2013-07-02 14:50:19 +02:00
GlobalStatus = ExitCritical
ExitMsg + = " CRITICAL : %s " % elementNameValue
if ( interpretStatus == ExitWarning and GlobalStatus != ExitCritical ) :
2017-01-24 19:06:35 +01:00
verboseoutput ( " Global exit set to WARNING " )
2013-07-02 14:50:19 +02:00
GlobalStatus = ExitWarning
ExitMsg + = " WARNING : %s " % elementNameValue
# Added the following for when GlobalStatus is ExitCritical and a warning is detected
# This way the ExitMsg gets added but GlobalStatus isn't changed
if ( interpretStatus == ExitWarning and GlobalStatus == ExitCritical ) : # ARR
ExitMsg + = " WARNING : %s " % elementNameValue #ARR
# Added the following so that GlobalStatus gets set to OK if there's no warning or critical
if ( interpretStatus == ExitOK and GlobalStatus != ExitWarning and GlobalStatus != ExitCritical ) : #ARR
GlobalStatus = ExitOK #ARR
# Dell, Intel, IBM and unknown hardware check
elif ( vendor == " dell " or vendor == " intel " or vendor == " ibm " or vendor == " unknown " ) :
# Added 20121027 As long as Dell doesnt correct these CIM elements return code we have to ignore it
ignore_list . append ( " System Board 1 Riser Config Err 0: Connected " )
2015-06-10 12:47:12 +02:00
ignore_list . append ( " Add-in Card 4 PEM Presence 0: Connected " )
2013-07-02 14:50:19 +02:00
if instance [ ' OperationalStatus ' ] is not None :
elementStatus = instance [ ' OperationalStatus ' ] [ 0 ]
verboseoutput ( " Element Op Status = %d " % elementStatus )
interpretStatus = {
0 : ExitOK , # Unknown
1 : ExitCritical , # Other
2 : ExitOK , # OK
3 : ExitWarning , # Degraded
4 : ExitWarning , # Stressed
5 : ExitWarning , # Predictive Failure
6 : ExitCritical , # Error
7 : ExitCritical , # Non-Recoverable Error
8 : ExitWarning , # Starting
9 : ExitWarning , # Stopping
10 : ExitCritical , # Stopped
11 : ExitOK , # In Service
12 : ExitWarning , # No Contact
13 : ExitCritical , # Lost Communication
14 : ExitCritical , # Aborted
15 : ExitOK , # Dormant
16 : ExitCritical , # Supporting Entity in Error
17 : ExitOK , # Completed
18 : ExitOK , # Power Mode
19 : ExitOK , # DMTF Reserved
20 : ExitOK # Vendor Reserved
} [ elementStatus ]
if ( interpretStatus == ExitCritical ) :
verboseoutput ( " Global exit set to CRITICAL " )
GlobalStatus = ExitCritical
ExitMsg + = " CRITICAL : %s " % elementNameValue
if ( interpretStatus == ExitWarning and GlobalStatus != ExitCritical ) :
2017-01-24 19:06:35 +01:00
verboseoutput ( " Global exit set to WARNING " )
2013-07-02 14:50:19 +02:00
GlobalStatus = ExitWarning
ExitMsg + = " WARNING : %s " % elementNameValue
# Added same logic as in 20100702 here, otherwise Dell servers would return UNKNOWN instead of OK
if ( interpretStatus == ExitWarning and GlobalStatus == ExitCritical ) : # ARR
ExitMsg + = " WARNING : %s " % elementNameValue #ARR
if ( interpretStatus == ExitOK and GlobalStatus != ExitWarning and GlobalStatus != ExitCritical ) : #ARR
GlobalStatus = ExitOK #ARR
if elementName == ' Server Blade ' :
if SerialNumber :
if SerialNumber . find ( " . " ) != - 1 :
SerialNumber = SerialNumber . split ( ' . ' ) [ 1 ]
# Munge the ouptput to give links to documentation and warranty info
if ( urlise_country != ' ' ) :
SerialNumber = urlised_serialnumber ( vendor , urlise_country , SerialNumber )
server_info = urlised_server_info ( vendor , urlise_country , server_info )
2014-09-09 17:28:53 +02:00
# If this is a blade server, also output chassis serial number as additional info
if ( isblade == " yes " ) :
SerialNumber + = " Chassis S/N: %s " % ( SerialChassis )
2022-07-08 06:44:09 +02:00
xdata [ ' ChassisSerialNumber ' ] = SerialChassis
2014-09-09 17:28:53 +02:00
2013-07-02 14:50:19 +02:00
# Output performance data
perf = ' | '
if perfdata :
sdata = [ ]
ctr = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 ]
# sort the data so we always get perfdata in the right order
# we make no assumptions about the order in which CIM returns data
# first sort by element name (effectively) and insert sequence numbers
for p in sorted ( data ) :
p1 = p [ 1 ]
sdata . append ( ( " P %d %s _ %d _ %s " ) % ( p1 , perf_Prefix [ p1 ] , ctr [ p1 ] , p [ 0 ] ) )
ctr [ p1 ] + = 1
# then sort perfdata into groups and output perfdata string
for p in sorted ( sdata ) :
perf + = p
# sanitise perfdata - don't output "|" if nothing to report
if perf == ' | ' :
perf = ' '
2020-07-10 07:30:43 +02:00
# Cleanup temporary openssl config
if sslproto :
os . remove ( sslconfpath )
2022-07-08 06:44:09 +02:00
xdata [ ' GlobalStatus ' ] = GlobalStatus
2013-07-02 14:50:19 +02:00
if GlobalStatus == ExitOK :
2022-07-08 06:44:09 +02:00
if format == ' string ' :
2022-12-30 08:57:39 +01:00
print ( " OK - Server: %s s/n: %s %s %s " % ( server_info , SerialNumber , bios_info , perf ) )
2022-07-08 06:44:09 +02:00
else :
xdataprint ( )
2013-07-02 14:50:19 +02:00
elif GlobalStatus == ExitUnknown :
2022-07-08 06:44:09 +02:00
if format == ' string ' :
print ( " UNKNOWN: %s " % ( ExitMsg ) ) #ARR
else :
xdataprint ( )
2013-07-02 14:50:19 +02:00
else :
2022-07-08 06:44:09 +02:00
if format == ' string ' :
print ( " %s - Server: %s %s %s %s " % ( ExitMsg , server_info , ' s/n: ' + SerialNumber , bios_info , perf ) )
else :
xdataprint ( )
2013-07-02 14:50:19 +02:00
sys . exit ( GlobalStatus )