Hulla/Guten Tag/Hello/ Bonjour,
I've managed to throw together a script that will work with ESXi via WBEM however It has not been fully tested. It is still a beta release however if feel free to do with as you see fit. The script is essentially a port of David Ligeret's check_ESXi_WBEM.py.
Ive tested it on Dell Hardware with the DELL specific ESXi Install however have not had a chance to test it on HP machines. I know there are reports of Earlier Versions of the HP installs not supporting the hardware specific Class(es). HP has supposedly fixed this in later releases however i have not been able to verify this. .
If anyone is curious in helping with testing the HP side of things let me know, I just don't have any suitable testing environments.
As usual comments, criticism, improvements are all welcome.
Thanks,
Jazz Alyxzander Turner-Baggs
::Patch Log::
7/1/2009 - Fixed Syntax error in Exception handling + added utilitys for IDE Debug.
CODE
--[[
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE
--]]
ScriptName= "Beta - WBEM_ESXi_OperationalStatus"
date= "Jun 14, 2009"
Author = "Jazz Alyxzander Turner-Baggs"
VersionMaj = 0
VersionMin = 8
Description = "Detects any errors on a ESXi Machine - DELL"
----------------------------------------------------------------
--[[
Documentation:
This Script is Based Entirely off of Check_ESXi_WBEM.py by David Ligeret.
http://communities.vmware.com/docs/DOC-7170
BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA
***Currently Only Tested With Dell Hardware with the DELL flavor of ESXi***
BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA
The Following Script Loops over a set of Classes and enumerates all Instances. The
OperationalStatus property is pulled from each Instance and compared Against a
value in the Status Table.
If that Status is defined as OK then then it is not added to the error String. If
any Errors are Detected the Script alarms.
--]]
-----------------------------------------------------------------
--[[
ToDo:
- Add WQL -> Raw XML function
- Make Pretty
--]]
-----------------------------------------------------------------
-----------------------------------------------------------------------------------
--------------------------------WBEM Class-----------------------------------------
--[[
CLASS: J_WBEM
AUTHOR: JAzz Alyxzander Turner-Baggs
DESC: Generic WBEM Class that can be used Much Like TLuaWMIQuery and TLuaHTTPClient
USAGE:
A = J_WBEM.new()
A:Connect(user,pass)
A:Query(query)
while A:NextInstance() do
print( A:GetProperty(Property)
end
--]]
J_WBEM = {}
J_WBEM.__index = J_WBEM
--[[
Desc: Alertnative Constructor
Parameters <None>
ReturnValue J_WBEM Object if successfull
Notes
--]]
function J_WBEM.new_default()
local wbem = {}
setmetatable(wbem,J_WBEM)
wbem.inst = ""
wbem.error = ""
wbem.conn = ""
wbem.data = ""
--Defaults
wbem.URI = "\\cimom"
wbem.port_num = 5989
wbem.use_https = true
return wbem
end
--[[
Desc: Constructor
Parameters Int PortNumber, Bool use_Https, string URI
ReturnValue WBEM Object if successfull
Notes Calling this function with no parameters results in invocation of the alternative Constructor
--]]
function J_WBEM.new(port,secure, uri)
local wbem = {}
setmetatable(wbem,J_WBEM)
-- Function Overloading Hack
if uri== nil then
return J_WBEM.new_default()
elseif secure ~= nil and uri ~= nil then
wbem.inst = ""
wbem.error = ""
wbem.conn = ""
wbem.data = ""
wbem.URI = uri
wbem.port_num = port
wbem.use_https = secure
return wbem
else
print("Ill Formatted Parameters.")
end
end
--[[
Desc: Send Query to Server and stores Content in Object
Parameters <None>
ReturnValue True If Successfull
Notes
--]]
function J_WBEM:Query()
self.conn:Post(sURI, Extra_Headers, wbem_query)
self.data = self.conn:GetContent(1)
if string.len(self.data) == nil then
self.error = "Unable to Query"
return false
elseif string.len(self.data) == 0 then
self.error = "No Data Returned, check User and Pass"
return false
else
return true
end
end
--[[
Desc: Opens Connection to the Network Object
Parameters String Username, String PAssword
ReturnValue True if Successfull
Notes uses parameters from Initialization
--]]
function J_WBEM:Connect(user,pass)
self.conn = TLuaHTTPClient()
local iRet = self.conn:Connect(self.port_num,self.use_https, user, pass )
if iRet == 0 then
self.error = "Unable To Establish a Connection"
return false
end
return true
end
--[[
Desc: Loads Next instance into object
Parameters <none>
ReturnValue Returns True if an instance was found, false otherwise
Notes Can only be called after a Query
--]]
function J_WBEM:NextInstance()
_,_,inst_class_name,self.inst, self.data= string.find(self.data,[[<INSTANCE CLASSNAME="(.-)">(.-)</INSTANCE>(.+)]])
if self.inst == nil then
return false
else
return true
end
end
--[[
Desc: Returns Property From Current Instance
Parameters string name_of_property
ReturnValue Boolean was_Successfull, <variable> PropertyValue
Notes Can only be called after NextInstance() has been invoked
Arrays are returned as Tables all others returned as string.
--]]
function J_WBEM:GetProperty(prop_name)
_,_, prop_type , data_type, prop_data = string.find(self.inst,"<PROPERTY%.?(%w-) NAME=\""..prop_name.."\" TYPE=(.-)>(.-)</PROPERTY%.?%1>")
if prop_type == nil then
print("Error No property Found")
return false,nil
end
if prop_type == "ARRAY" then
prop_value = {}
s,f,values = string.find(prop_data,"<VALUE.ARRAY>(.-)</VALUE.ARRAY>")
while values ~= nil do
_,_,val,values = string.find(values,"<VALUE>(.-)</VALUE>(.+)")
table.insert(prop_value,val)
end
else
_,_,prop_value = string.find(prop_data,"<VALUE>(.-)</VALUE>")
end
return true,prop_value
end
--[[
Desc: Returns Last Error
Parameters <None>
ReturnValue String Error
Notes Not a Whole lot of testing done here to be honest..
--]]
function J_WBEM:GetLastError()
return self.error
end
---------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
-- Status Translation Table
status_table = {}
table.insert(status_table,"0","OK(Unknown)") -- Unknown
table.insert(status_table,"1","Critical(Other)") -- Other
table.insert(status_table,"2","OK(OK)") -- OK
table.insert(status_table,"3","Warning(Degraded)") -- Degraded
table.insert(status_table,"4","Warning(Stressed)") -- Stressed
table.insert(status_table,"5","Warning(Predictive Failure)") -- Predictive Failure
table.insert(status_table,"6","Critical(Error)") -- Error
table.insert(status_table,"7","Critical(Non-Recoverable Error)") -- Non-Recoverable Error
table.insert(status_table,"8","Warning(Starting)") -- Starting
table.insert(status_table,"9","Warning(Stopping)") -- Stopping
table.insert(status_table,"10","Critical(Stopped)") -- Stopped
table.insert(status_table,"11","OK(In Service)") -- In Service
table.insert(status_table,"12","Warning(No Contact)") -- No Contact
table.insert(status_table,"13","Critical(Lost Communication)") -- Lost Communication
table.insert(status_table,"14","Critical(Aborted)") -- Aborted
table.insert(status_table,"15","OK(Dormant)") -- Dormant
table.insert(status_table,"16","Critical(Supporting Entity in Error)") -- Supporting Entity in Error
table.insert(status_table,"17","OK(Completed)") -- Completed
table.insert(status_table,"18","OK(Power Mode)") -- Power Mode
table.insert(status_table,"19","OK(DMTF Reserved)") -- DMTF Reserved
table.insert(status_table,"20","OK(Vendor Reserved)") -- Vendor Reserved
-- End Status Translation Table
function OnConfigure()
Config = LuaScriptConfigurator()
Config:SetAuthor(Author)
Config:SetDescription(Description)
Config:SetMinBuildVersion(0)
Config:SetScriptVersion(VersionMaj, VersionMin )
if IsIDE() then
Config:AddArgument("username", "",LuaScriptConfigurator.CHECK_NOT_EMPTY)
Config:AddArgument("password", "",LuaScriptConfigurator.CHECK_NOT_EMPTY)
end
Config:SetEntryPoint("main")
return Config
end
function main()
DEBUG = true
--Initialize Variables
user_name = GetAccountUser()
password = GetAccountPassword()
if IsIDE() then
user_name = GetArgument(0)
password = GetArgument(1)
end
error_string = ""
property_to_query = "OperationalStatus" -- Property To pull status
inst_ID_prop = "ElementName" -- Property To Identify Instance
classes = { "CIM_ComputerSystem", -- List of Classes to enumerate
"CIM_NumericSensor",
"CIM_Memory",
"CIM_Processor",
"CIM_RecordLog",
"OMC_DiscreteSensor",
"VMware_StorageExtent",
"VMware_Controller",
"VMware_StorageVolume",
"VMware_Battery",
"VMware_SASSATAPort"
}
-- For every Class, Get Operational State of all Instances and compare to value in Status-Table
for __,class in pairs(classes) do
if DEBUG then
print("Class: " .. class)
end
wbem_query = [[<?xml version="1.0" encoding="utf-8" ?>
<CIM CIMVERSION="2.0" DTDVERSION="2.0">
<MESSAGE ID="1001" PROTOCOLVERSION="1.0">
<SIMPLEREQ>
<IMETHODCALL NAME="EnumerateInstances">
<LOCALNAMESPACEPATH>
<NAMESPACE NAME="root"/>
<NAMESPACE NAME="cimv2"/>
</LOCALNAMESPACEPATH>
<IPARAMVALUE NAME="ClassName">
<CLASSNAME NAME="]] .. class .. [["/>
</IPARAMVALUE>
</IMETHODCALL>
</SIMPLEREQ>
</MESSAGE>
</CIM>]]
--WBEM = J_WBEM.new("\cimom",5989,true)
WBEM = J_WBEM.new()
if not WBEM:Connect(user_name , password) then
SetExitStatus("Error - " .. WBEM:GetLastError(),false)
return
end
if not WBEM:Query(wbem_query) then
SetExitStatus("Error - Query Failed: " .. WBEM:GetLastError(),false)
return
end
while WBEM:NextInstance() do
--Get Property
bOk,inst_state = WBEM:GetProperty(property_to_query)
bOk,inst_name = WBEM:GetProperty(inst_ID_prop)
-- Pulls the first element from the Array
if inst_state ~= nil and type(inst_state) == "table" then
inst_state = inst_state[1]
end
--Check that State is OK
if inst_state ~= nil then
--
state_str = status_table[tonumber(inst_state)]
_,_,status,status_details = string.find(state_str,"(.+)%((.+)%)")
if status ~= "OK" then
error_string = error_string .. status ..": " .. inst_name .. "\n"
end
end
end
end
-- Summarize & Return
if error_string == "" then
error_string = "OK"
SetExitStatus("OK",true )
else
error_string = "\n" .. error_string
SetExitStatus("Error: " .. error_string,false)
end
end
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE
--]]
ScriptName= "Beta - WBEM_ESXi_OperationalStatus"
date= "Jun 14, 2009"
Author = "Jazz Alyxzander Turner-Baggs"
VersionMaj = 0
VersionMin = 8
Description = "Detects any errors on a ESXi Machine - DELL"
----------------------------------------------------------------
--[[
Documentation:
This Script is Based Entirely off of Check_ESXi_WBEM.py by David Ligeret.
http://communities.vmware.com/docs/DOC-7170
BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA
***Currently Only Tested With Dell Hardware with the DELL flavor of ESXi***
BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA _ BETA
The Following Script Loops over a set of Classes and enumerates all Instances. The
OperationalStatus property is pulled from each Instance and compared Against a
value in the Status Table.
If that Status is defined as OK then then it is not added to the error String. If
any Errors are Detected the Script alarms.
--]]
-----------------------------------------------------------------
--[[
ToDo:
- Add WQL -> Raw XML function
- Make Pretty
--]]
-----------------------------------------------------------------
-----------------------------------------------------------------------------------
--------------------------------WBEM Class-----------------------------------------
--[[
CLASS: J_WBEM
AUTHOR: JAzz Alyxzander Turner-Baggs
DESC: Generic WBEM Class that can be used Much Like TLuaWMIQuery and TLuaHTTPClient
USAGE:
A = J_WBEM.new()
A:Connect(user,pass)
A:Query(query)
while A:NextInstance() do
print( A:GetProperty(Property)
end
--]]
J_WBEM = {}
J_WBEM.__index = J_WBEM
--[[
Desc: Alertnative Constructor
Parameters <None>
ReturnValue J_WBEM Object if successfull
Notes
--]]
function J_WBEM.new_default()
local wbem = {}
setmetatable(wbem,J_WBEM)
wbem.inst = ""
wbem.error = ""
wbem.conn = ""
wbem.data = ""
--Defaults
wbem.URI = "\\cimom"
wbem.port_num = 5989
wbem.use_https = true
return wbem
end
--[[
Desc: Constructor
Parameters Int PortNumber, Bool use_Https, string URI
ReturnValue WBEM Object if successfull
Notes Calling this function with no parameters results in invocation of the alternative Constructor
--]]
function J_WBEM.new(port,secure, uri)
local wbem = {}
setmetatable(wbem,J_WBEM)
-- Function Overloading Hack
if uri== nil then
return J_WBEM.new_default()
elseif secure ~= nil and uri ~= nil then
wbem.inst = ""
wbem.error = ""
wbem.conn = ""
wbem.data = ""
wbem.URI = uri
wbem.port_num = port
wbem.use_https = secure
return wbem
else
print("Ill Formatted Parameters.")
end
end
--[[
Desc: Send Query to Server and stores Content in Object
Parameters <None>
ReturnValue True If Successfull
Notes
--]]
function J_WBEM:Query()
self.conn:Post(sURI, Extra_Headers, wbem_query)
self.data = self.conn:GetContent(1)
if string.len(self.data) == nil then
self.error = "Unable to Query"
return false
elseif string.len(self.data) == 0 then
self.error = "No Data Returned, check User and Pass"
return false
else
return true
end
end
--[[
Desc: Opens Connection to the Network Object
Parameters String Username, String PAssword
ReturnValue True if Successfull
Notes uses parameters from Initialization
--]]
function J_WBEM:Connect(user,pass)
self.conn = TLuaHTTPClient()
local iRet = self.conn:Connect(self.port_num,self.use_https, user, pass )
if iRet == 0 then
self.error = "Unable To Establish a Connection"
return false
end
return true
end
--[[
Desc: Loads Next instance into object
Parameters <none>
ReturnValue Returns True if an instance was found, false otherwise
Notes Can only be called after a Query
--]]
function J_WBEM:NextInstance()
_,_,inst_class_name,self.inst, self.data= string.find(self.data,[[<INSTANCE CLASSNAME="(.-)">(.-)</INSTANCE>(.+)]])
if self.inst == nil then
return false
else
return true
end
end
--[[
Desc: Returns Property From Current Instance
Parameters string name_of_property
ReturnValue Boolean was_Successfull, <variable> PropertyValue
Notes Can only be called after NextInstance() has been invoked
Arrays are returned as Tables all others returned as string.
--]]
function J_WBEM:GetProperty(prop_name)
_,_, prop_type , data_type, prop_data = string.find(self.inst,"<PROPERTY%.?(%w-) NAME=\""..prop_name.."\" TYPE=(.-)>(.-)</PROPERTY%.?%1>")
if prop_type == nil then
print("Error No property Found")
return false,nil
end
if prop_type == "ARRAY" then
prop_value = {}
s,f,values = string.find(prop_data,"<VALUE.ARRAY>(.-)</VALUE.ARRAY>")
while values ~= nil do
_,_,val,values = string.find(values,"<VALUE>(.-)</VALUE>(.+)")
table.insert(prop_value,val)
end
else
_,_,prop_value = string.find(prop_data,"<VALUE>(.-)</VALUE>")
end
return true,prop_value
end
--[[
Desc: Returns Last Error
Parameters <None>
ReturnValue String Error
Notes Not a Whole lot of testing done here to be honest..
--]]
function J_WBEM:GetLastError()
return self.error
end
---------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
-- Status Translation Table
status_table = {}
table.insert(status_table,"0","OK(Unknown)") -- Unknown
table.insert(status_table,"1","Critical(Other)") -- Other
table.insert(status_table,"2","OK(OK)") -- OK
table.insert(status_table,"3","Warning(Degraded)") -- Degraded
table.insert(status_table,"4","Warning(Stressed)") -- Stressed
table.insert(status_table,"5","Warning(Predictive Failure)") -- Predictive Failure
table.insert(status_table,"6","Critical(Error)") -- Error
table.insert(status_table,"7","Critical(Non-Recoverable Error)") -- Non-Recoverable Error
table.insert(status_table,"8","Warning(Starting)") -- Starting
table.insert(status_table,"9","Warning(Stopping)") -- Stopping
table.insert(status_table,"10","Critical(Stopped)") -- Stopped
table.insert(status_table,"11","OK(In Service)") -- In Service
table.insert(status_table,"12","Warning(No Contact)") -- No Contact
table.insert(status_table,"13","Critical(Lost Communication)") -- Lost Communication
table.insert(status_table,"14","Critical(Aborted)") -- Aborted
table.insert(status_table,"15","OK(Dormant)") -- Dormant
table.insert(status_table,"16","Critical(Supporting Entity in Error)") -- Supporting Entity in Error
table.insert(status_table,"17","OK(Completed)") -- Completed
table.insert(status_table,"18","OK(Power Mode)") -- Power Mode
table.insert(status_table,"19","OK(DMTF Reserved)") -- DMTF Reserved
table.insert(status_table,"20","OK(Vendor Reserved)") -- Vendor Reserved
-- End Status Translation Table
function OnConfigure()
Config = LuaScriptConfigurator()
Config:SetAuthor(Author)
Config:SetDescription(Description)
Config:SetMinBuildVersion(0)
Config:SetScriptVersion(VersionMaj, VersionMin )
if IsIDE() then
Config:AddArgument("username", "",LuaScriptConfigurator.CHECK_NOT_EMPTY)
Config:AddArgument("password", "",LuaScriptConfigurator.CHECK_NOT_EMPTY)
end
Config:SetEntryPoint("main")
return Config
end
function main()
DEBUG = true
--Initialize Variables
user_name = GetAccountUser()
password = GetAccountPassword()
if IsIDE() then
user_name = GetArgument(0)
password = GetArgument(1)
end
error_string = ""
property_to_query = "OperationalStatus" -- Property To pull status
inst_ID_prop = "ElementName" -- Property To Identify Instance
classes = { "CIM_ComputerSystem", -- List of Classes to enumerate
"CIM_NumericSensor",
"CIM_Memory",
"CIM_Processor",
"CIM_RecordLog",
"OMC_DiscreteSensor",
"VMware_StorageExtent",
"VMware_Controller",
"VMware_StorageVolume",
"VMware_Battery",
"VMware_SASSATAPort"
}
-- For every Class, Get Operational State of all Instances and compare to value in Status-Table
for __,class in pairs(classes) do
if DEBUG then
print("Class: " .. class)
end
wbem_query = [[<?xml version="1.0" encoding="utf-8" ?>
<CIM CIMVERSION="2.0" DTDVERSION="2.0">
<MESSAGE ID="1001" PROTOCOLVERSION="1.0">
<SIMPLEREQ>
<IMETHODCALL NAME="EnumerateInstances">
<LOCALNAMESPACEPATH>
<NAMESPACE NAME="root"/>
<NAMESPACE NAME="cimv2"/>
</LOCALNAMESPACEPATH>
<IPARAMVALUE NAME="ClassName">
<CLASSNAME NAME="]] .. class .. [["/>
</IPARAMVALUE>
</IMETHODCALL>
</SIMPLEREQ>
</MESSAGE>
</CIM>]]
--WBEM = J_WBEM.new("\cimom",5989,true)
WBEM = J_WBEM.new()
if not WBEM:Connect(user_name , password) then
SetExitStatus("Error - " .. WBEM:GetLastError(),false)
return
end
if not WBEM:Query(wbem_query) then
SetExitStatus("Error - Query Failed: " .. WBEM:GetLastError(),false)
return
end
while WBEM:NextInstance() do
--Get Property
bOk,inst_state = WBEM:GetProperty(property_to_query)
bOk,inst_name = WBEM:GetProperty(inst_ID_prop)
-- Pulls the first element from the Array
if inst_state ~= nil and type(inst_state) == "table" then
inst_state = inst_state[1]
end
--Check that State is OK
if inst_state ~= nil then
--
state_str = status_table[tonumber(inst_state)]
_,_,status,status_details = string.find(state_str,"(.+)%((.+)%)")
if status ~= "OK" then
error_string = error_string .. status ..": " .. inst_name .. "\n"
end
end
end
end
-- Summarize & Return
if error_string == "" then
error_string = "OK"
SetExitStatus("OK",true )
else
error_string = "\n" .. error_string
SetExitStatus("Error: " .. error_string,false)
end
end
