#!/usr/bin/python

# -*- coding: UTF-8 -*-

#

# Script for checking global health of host running VMware ESX/ESXi

#

# Licence : GNU General Public Licence (GPL) http://www.gnu.org/

# Pre-req : pywbem

#

# The VMware 4.1 CIM API is documented here:

#

# http://www.vmware.com/support/developer/cim-sdk/4.1/smash/cim_smash_410_prog.pdf

#

# http://www.vmware.com/support/developer/cim-sdk/smash/u2/ga/apirefdoc/

#

# This Nagios plugin is maintained here:

# http://www.claudiokuenzler.com/nagios-plugins/check_esxi_hardware.php

#

#@---------------------------------------------------

#@ 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

#@---------------------------------------------------

import sys

sys.path.append('/usr/local/rnt/lib/python2.6/site-packages/')

import time

import pywbem

import re

import signal

#import string

from optparse import OptionParser,OptionGroup

myversion = '20110704'

NS = 'root/cimv2'

# 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 = []

# parameters

vendor = 'unknown'

hosturl = ''

# host name

hostname=''

# user

user=''

# password

password=''

# verbose

verbose=False

# timeout

timeout = 0

# urlise model and tag numbers (currently only Dell supported, but the code does the right thing for other vendors)

urlise_country=''

# define exit codes

ExitOK = 0

ExitWarning = 1

ExitCritical = 2

ExitUnknown = 3

def handler():

print 'CRITICAL: Execution time too long!'

sys.exit(ExitCritical)

def urlised_server_info(myvendor, server_info):

#server_inf = server_info

if myvendor == 'dell' :

# Dell support URLs (idea and tables borrowed from check_openmanage)

du = 'http://support.dell.com/support/edocs/systems/pe'

if (server_info is not None) :

p=re.match('(.*)PowerEdge (.*) (.*)',server_info)

if (p is not None) :

md=p.group(2)

if (re.match('M',md)) :

md = 'm'

server_info = p.group(1) + '<a href="' + du + md + '/">PowerEdge ' + p.group(2)+'</a> ' + p.group(3)

elif myvendor == 'hp':

return server_info

elif myvendor == 'ibm':

return server_info

elif myvendor == 'intel':

return server_info

return server_info

# ----------------------------------------------------------------------

def system_tag_url(myvendor,country):

url = {'xx':''}

if myvendor == 'dell':

# Dell support sites

supportsite = { 'emea':'http://support.euro.dell.com/support/topics/topic.aspx/emea/shared/support/my_systems_info/',

'ap':'http://supportapj.dell.com/support/topics/topic.aspx/ap/shared/support/my_systems_info/en/details?',

'glob':'http://support.dell.com/support/topics/global.aspx/support/my_systems_info/details?'}

# warranty URLs for different country codes

# EMEA

url['at'] = supportsite['emea'] + 'de/details?c=at&l=de&ServiceTag=' # Austria

url['be'] = supportsite['emea'] + 'nl/details?c=be&l=nl&ServiceTag=' # Belgium

url['cz'] = supportsite['emea'] + 'cs/details?c=cz&l=cs&ServiceTag=' # Czech Republic

url['de'] = supportsite['emea'] + 'de/details?c=de&l=de&ServiceTag=' # Germany

url['dk'] = supportsite['emea'] + 'da/details?c=dk&l=da&ServiceTag=' # Denmark

url['es'] = supportsite['emea'] + 'es/details?c=es&l=es&ServiceTag=' # Spain

url['fi'] = supportsite['emea'] + 'fi/details?c=fi&l=fi&ServiceTag=' # Finland

url['fr'] = supportsite['emea'] + 'fr/details?c=fr&l=fr&ServiceTag=' # France

url['gr'] = supportsite['emea'] + 'en/details?c=gr&l=el&ServiceTag=' # Greece

url['it'] = supportsite['emea'] + 'it/details?c=it&l=it&ServiceTag=' # Italy

url['il'] = supportsite['emea'] + 'en/details?c=il&l=en&ServiceTag=' # Israel

url['me'] = supportsite['emea'] + 'en/details?c=me&l=en&ServiceTag=' # Middle East

url['no'] = supportsite['emea'] + 'no/details?c=no&l=no&ServiceTag=' # Norway

url['nl'] = supportsite['emea'] + 'nl/details?c=nl&l=nl&ServiceTag=' # The Netherlands

url['pl'] = supportsite['emea'] + 'pl/details?c=pl&l=pl&ServiceTag=' # Poland

url['pt'] = supportsite['emea'] + 'en/details?c=pt&l=pt&ServiceTag=' # Portugal

url['ru'] = supportsite['emea'] + 'ru/details?c=ru&l=ru&ServiceTag=' # Russia

url['se'] = supportsite['emea'] + 'sv/details?c=se&l=sv&ServiceTag=' # Sweden

url['uk'] = supportsite['emea'] + 'en/details?c=uk&l=en&ServiceTag=' # United Kingdom

url['za'] = supportsite['emea'] + 'en/details?c=za&l=en&ServiceTag=' # South Africa

# America

url['br'] = supportsite['glob'] + 'c=br&l=pt&ServiceTag=' # Brazil

url['ca'] = supportsite['glob'] + 'c=ca&l=en&ServiceTag=' # Canada

url['mx'] = supportsite['glob'] + 'c=mx&l=es&ServiceTag=' # Mexico

url['us'] = supportsite['glob'] + 'c=us&l=en&ServiceTag=' # USA

# Asia/Pacific

url['au'] = supportsite['ap'] + 'c=au&l=en&ServiceTag=' # Australia

url['cn'] = supportsite['ap'] + 'c=cn&l=zh&ServiceTag=' # China

url['in'] = supportsite['ap'] + 'c=in&l=en&ServiceTag=' # India

# default fallback

url['xx'] =supportsite['glob'] + 'ServiceTag=' # default

# elif vendor == 'hp':

# elif vendor == 'ibm':

# elif vendor == 'intel':

return url.get(country,url['xx'])

# ----------------------------------------------------------------------

def urlised_serialnumber(myvendor,country,SerialNumber):

if SerialNumber is not None :

tu = system_tag_url(myvendor,country)

if tu != '' :

SerialNumber = '<a href="' + tu + SerialNumber + '">' + SerialNumber + '</a>'

return SerialNumber

# ----------------------------------------------------------------------

def verboseoutput(message) :

if verbose:

print "%s %s" % (time.strftime("%Y%m%d %H:%M:%S"), message)

# ----------------------------------------------------------------------

def getopts() :

global hosturl,user,password,vendor,verbose,urlise_country,timeout,get_power,get_volts,get_current,get_temp,get_fan,hostname

usage = "usage: %prog https://hostname user password system [verbose]\n" \

"example: %prog https://my-shiny-new-vmware-server root fakepassword dell\n\n" \

"or, using new style options:\n\n" \

"usage: %prog -H hostname -U username -P password [-V system -v -p -I XX]\n" \

"example: %prog -H my-shiny-new-vmware-server -U root -P fakepassword -V auto -I uk\n\n" \

"or, verbosely:\n\n" \

"usage: %prog --host=hostname --user=username --pass=password [--vendor=system --verbose --html=XX]\n"

parser = OptionParser(usage=usage, version="%prog "+myversion)

group1 = OptionGroup(parser, 'Mandatory parameters')

group2 = OptionGroup(parser, 'Optional parameters')

group1.add_option("-H", "--host", dest="host", help="report on HOST", metavar="HOST")

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")

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("-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)")

parser.add_option_group(group1)

parser.add_option_group(group2)

# check input arguments

if len(sys.argv) < 2:

print "no parameters specified\n"

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:

print "too few parameters\n"

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]:

print "mandatory parameter '--" + m + "' is missing\n"

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

vendor=options.vendor.lower()

verbose=options.verbose

urlise_country=options.urlise_country.lower()

timeout=options.timeout

# 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()

# ----------------------------------------------------------------------

def parse_vendor(myvendor,wbemclient):

# if vendor is specified as 'auto', try to get vendor from CIM

# note: the default vendor is 'unknown'

if myvendor=='auto':

c=wbemclient.EnumerateInstances('CIM_Chassis')

man=c[0][u'Manufacturer']

if re.match("Dell",man):

myvendor="dell"

elif re.match("HP",man):

myvendor="hp"

elif re.match("IBM",man):

myvendor="ibm"

elif re.match("Intel",man):

myvendor="intel"

else:

myvendor='unknown'

return myvendor

def main():

global vendor

getopts()

# connection to host

verboseoutput("Connection to "+hosturl)

wbemclient = pywbem.WBEMConnection(hosturl, (user,password), NS)

# Add a timeout for the script. When using with Nagios, the Nagios timeout cannot be < than plugin timeout.

if 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 = ""

vendor = parse_vendor(vendor,wbemclient)

for classe in ClassesToCheck :

verboseoutput("Check classe "+classe)

try:

instance_list = wbemclient.EnumerateInstances(classe)

except pywbem.cim_operations.CIMError,args:

if ( args[1].find('Socket error') >= 0 ):

print "CRITICAL: %s" %args

sys.exit (ExitCritical)

else:

verboseoutput("Unknown CIM Error: %s" % args)

except pywbem.cim_http.AuthError:

verboseoutput("Global exit set to CRITICAL")

GlobalStatus = ExitCritical

ExitMsg = " : Authentication Error! "

else:

# GlobalStatus = ExitOK #ARR

for instance in instance_list :

elementName = instance['ElementName']

elementNameValue = elementName

verboseoutput(" Element Name = "+elementName)

# 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'])

elif elementName == 'Chassis' :

man = instance[u'Manufacturer']

verboseoutput(" Manufacturer = "+man)

SerialNumber = instance[u'SerialNumber']

if SerialNumber:

verboseoutput(" SerialNumber = "+SerialNumber)

server_info = man + ' '

if vendor != 'intel':

model = instance[u'Model']

if model:

verboseoutput(" Model = "+model)

server_info += model + ' s/n:'

elif elementName == 'Server Blade' :

SerialNumber = instance[u'SerialNumber']

if SerialNumber:

verboseoutput(" SerialNumber = "+SerialNumber)

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)

elif classe == "CIM_Processor" :

verboseoutput(" Family = %d" % instance['Family'])

verboseoutput(" CurrentClockSpeed = %dMHz" % 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) :

verboseoutput("GLobal exit set to CRITICAL")

GlobalStatus = ExitCritical

ExitMsg += " CRITICAL : %s " % elementNameValue

if (interpretStatus == ExitWarning and GlobalStatus != ExitCritical) :

verboseoutput("GLobal exit set to WARNING")

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") :

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) :

verboseoutput("GLobal exit set to WARNING")

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,server_info)

if GlobalStatus == ExitOK :

print "OK - Server: %s %s %s" % (server_info, SerialNumber, bios_info)

elif GlobalStatus == ExitUnknown :

print "UNKNOWN: %s" % (ExitMsg) #ARR

else:

print "%s- Server: %s %s %s" % (ExitMsg, server_info, SerialNumber, bios_info)

sys.exit (GlobalStatus)

if __name__ == "__main__":

main()