import os, time, commands, logging, pickle, datetime, ConfigParser, urllib2, httplib, base64, zlib, xml.etree.ElementTree as et
from random import randint
def print_dict(dictionary): return ', '.join(["'%s': %i" % (k, v) for k, v in sorted(dictionary.iteritems())])
def sizeof_fmt(num, suffix='B'):
for unit in ['','K','M','G','T','P','E','Z']:
if abs(num) < 1024.0:
return "%3.1f %s%s" % (num, unit, suffix)
num /= 1024.0
return "%.1f%s%s" % (num, 'Y', suffix)
def add_controller_number(controller, name):
if '(' in name:
k = name.rfind('(')
if name[k+1].isdigit():
return "%s%s/%s" % (name[:k+1], controller, name[k+1:])
return "%s (%s)" % (name, controller)
def check_sv_agent(scom_helper):
scom_helper.log.debug('Checking if ServerView Agent is present')
try:
# ver = commands.getoutput("srvmagt --version | grep -i ServerView | awk '{print $NF}'") # need root to execute
ver = commands.getoutput("head -n 250 /etc/srvmagt/srvmagt.sh 2>/dev/null | grep -i MYVERSION | awk '{print $1}'")
ver = "".join(i for i in ver if i in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '.'])
except:
ver = ""
if ver == "":
scom_helper.log.error('ServerView Agent not installed')
if scom_helper.type == MONITORING_SCRIPT: # we output this error only in monitoring script
scom_helper.output_error(2, 'ServerView Agent not installed') # only ServerView Health State component
exit(109)
if scom_helper.type == DISCOVERY_SCRIPT:
scom_helper.sv_agent_ver = ver
if ver < MIN_SV_VER:
msg = 'ServerView Agent version too old (%s)' % ver
scom_helper.log.error(msg)
scom_helper.output_error(1, msg) # ServerView Health State and ServerView Agents Version components
exit(112)
scom_helper.log.debug('ServerView Agent version: %s' % ver)
if scom_helper.type == DISCOVERY_SCRIPT: return
# Test if ServerView Agent is running
try:
count = commands.getoutput('ps aux | grep "[e]ecd" | wc -l')
except:
count = 0
if count == 0:
scom_helper.log.error('ServerView Agent not running')
scom_helper.output_error(1, 'ServerView Agent not running')
exit(111)
def check_amDaemon():
output = commands.getoutput("ls /usr/sbin/amDaemon 2>/dev/null | wc -l") # probably only root, but needed if so
is_amdaemon = int(output) if output != '' else 0
if is_amdaemon <= 0:
output = commands.getoutput("LC_ALL=C ls /usr/sbin/amDaemon 2>&1 | grep -i 'permission denied' | wc -l") # other users
is_amdaemon = int(output) if output != '' else 0
return is_amdaemon > 0
def get_other_failure_reason(health_list):
reason = ""
for instance in health_list:
if str(instance['elementname']) in ["DriverMonitor", "PCISlots", "TrustedPlatformModule"]:
if get_health(instance['healthstate']) != STATUS_OK:
reason += "%s failed; " % instance['elementname']
return reason
def get_failure_reason(cim, component, subsystem_number):
if subsystem_number in [FANS, TEMPERATURE, VOLTAGES, POWERCONSUMP]:
instances_list = cim.enumerate_instances(cim_classes[subsystem_number])
for instance in instances_list:
if instance['elementname'] == component:
return "%s %s" % (instance_name[subsystem_number], instance['currentstate'])
if subsystem_number in [PROCESSOR, MEMORY, MGMTCTRL, POWERSUPPLY]:
instances_list = cim.enumerate_instances(cim_classes[subsystem_number])
for instance in instances_list:
if instance['elementname'] == component:
result = ""
for status in instance['operationalstatus']:
result += ", %s" % CIM_OperationalStatus[int(status)]
if len(result) > 0:
return result[2:]
return ""
class Logger:
def __init__(self, username, logfile, script_type):
self.homedir = self.get_homedir(username)
self.script_type = script_type
(self.loglevel, self.logmode) = self.get_config()
self.alert_file = "/tmp/Fujitsu/" + PKG_NAME + ".log"
if not os.path.exists("/tmp/Fujitsu/"): os.makedirs("/tmp/Fujitsu/")
if not os.path.exists(self.alert_file): open(self.alert_file, 'w').close()
self.logfile = self.homedir + logfile
if self.loglevel == logging.DEBUG:
logging.basicConfig(filename=self.logfile, filemode=self.logmode, level=self.loglevel, format='%(asctime)s [%(levelname)s]: %(message)s')
else:
logging.basicConfig(level=self.loglevel, format='%(asctime)s [%(levelname)s]: %(message)s')
logging.debug('Python script version: __MP_VERSION__')
def get_homedir(self, username):
# in some cases expanding ~ return scx user home directory (root) or even file system root (SA #233567182)
homedir = commands.getoutput('cat /etc/passwd 2>/dev/null | grep -i %s | cut -d: -f6' % username).split("\n")[0]
if (homedir == ''): homedir = os.path.expanduser("~")
if (homedir == '/'): homedir = commands.getoutput('echo ~'+username)
homedir += "/." + PKG_NAME + "/"
if not os.path.exists(homedir): os.makedirs(homedir)
return homedir
def get_config(self):
loglevel = logging.ERROR
logmode = 'a'
config = ConfigParser.RawConfigParser()
if self.script_type == DISCOVERY_SCRIPT and not os.path.exists(self.homedir + LOG_NAME):
config.add_section('ServerDiscovery')
config.set('ServerDiscovery', 'DebugMode', 'no')
config.set('ServerDiscovery', 'OverWrite', 'no')
config.add_section('ComponentsMonitor')
config.set('ComponentsMonitor', 'DebugMode', 'no')
config.set('ComponentsMonitor', 'OverWrite', 'no')
config.add_section('PerformanceMonitor')
config.set('PerformanceMonitor', 'DebugMode', 'no')
config.set('PerformanceMonitor', 'OverWrite', 'no')
with open(self.homedir + LOG_NAME, 'wb') as configfile:
config.write(configfile)
else:
config.read(self.homedir + LOG_NAME)
tag_name = 'ServerDiscovery'
if self.script_type == MONITORING_SCRIPT: tag_name = 'ComponentsMonitor'
if self.script_type == PERFMON_SCRIPT: tag_name = 'PerformanceMonitor'
try:
if config.get(tag_name, 'DebugMode').lower() == 'yes':
loglevel = logging.DEBUG
if config.get(tag_name, 'OverWrite').lower() == 'yes':
logmode = 'w'
except ConfigParser.NoSectionError:
config.add_section(tag_name)
config.set(tag_name, 'DebugMode', 'no')
config.set(tag_name, 'OverWrite', 'no')
with open(self.homedir + LOG_NAME, 'wb') as configfile:
config.write(configfile)
except:
pass
return (loglevel, logmode)
def scom_alert(self, level, msg):
if self.script_type == DISCOVERY_SCRIPT: msg += ' (discovery script)'
if self.script_type == MONITORING_SCRIPT: msg += ' (monitoring script)'
if self.script_type == PERFMON_SCRIPT: msg += ' (perfmon script)'
if level == SCOM_ERROR: logging.error(msg)
if level == SCOM_INFO: logging.info(msg)
if level == SCOM_WARNING: logging.warning(msg)
ldate = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
msg = ldate + " " + scom_errors[level] + " " + msg
with open(self.alert_file, "a") as text_file:
text_file.write(msg + "\n")
def debug(self, msg): logging.debug(msg)
def error(self, msg): logging.error(msg)
def variable(self, name, value): logging.debug("%s = %s" % (name.ljust(29), value))
def component_debug(self, name, info):
logging.debug('Discovered components: %s' % name)
if info != "None":
logging.debug('Discovered component info: %s' % info)
class CIMClient:
def __init__(self, scom_helper, username, password, target, port, namespace='root/svs'):
self.scom = scom_helper
self.username = username
self.password = password
self.target = target
self.port = port
self.url = self._get_url()
self.namespace = namespace
self.check_mid = True
def _prepare_url(self, host, port, user, passwd):
url = "https://%s:%s/cimom" % (host, port)
httplib.HTTPConnection._http_vsn = 10
httplib.HTTPConnection._http_vsn_str = 'HTTP/1.0'
password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_manager.add_password(None, url, user, passwd)
auth_manager = urllib2.HTTPBasicAuthHandler(password_manager)
opener = urllib2.build_opener(auth_manager)
urllib2.install_opener(opener)
return url
def _get_url(self):
try:
cim_url = self._prepare_url(self.target, self.port, self.username, self.password)
except Exception as e:
msg = "108 Error preparing connection to CIMOM: %s (discovery script)" % e
self.scom.log.scom_alert(SCOM_ERROR, msg)
self.scom.output_error(2, msg) # only ServerView Health State component
exit(108)
return cim_url
def _get_localnamespacepath(self):
ns = self.namespace.split('/', 2)
return r"""<LOCALNAMESPACEPATH><NAMESPACE NAME="%s"/><NAMESPACE NAME="%s"/></LOCALNAMESPACEPATH>""" % (ns[0], ns[1])
def _build_instance_keybindings(self, ciminstance):
result = ""
for key in ciminstance:
if key != 'instanceclassname':
result += "<KEYBINDING NAME=\"%s\"><KEYVALUE VALUETYPE=\"%s\">%s</KEYVALUE></KEYBINDING>" % (key, ciminstance[key][0], ciminstance[key][1])
return result
def _get_instance_keybindings(self, cimclass, xmlinstance):
iresult = {}
if cimclass != None:
iresult['instanceclassname'] = cimclass
else:
iresult['instanceclassname'] = xmlinstance.find('.//INSTANCENAME').attrib["CLASSNAME"]
for key in xmlinstance.findall('.//KEYBINDING'):
value = key.find('.//KEYVALUE')
iresult[key.attrib['NAME']] = (value.attrib['VALUETYPE'], value.text)
return iresult
def _get_instance_properties(self, iresult, xmlinstance):
for i in xmlinstance.findall('.//PROPERTY'):
name = i.attrib['NAME'].lower()
if len(i) > 0:
iresult[name] = i[0].text
else:
iresult[name] = ''
for i in xmlinstance.findall('.//PROPERTY.ARRAY'):
name = i.attrib['NAME'].lower()
if len(i) > 0:
val = []
for j in i.findall('.//VALUE'):
val.append(j.text)
iresult[name] = val
else:
iresult[name] = []
def _build_message(self, msgid, method, cimclass, ciminstance=None, assocclass="", resultclass=""):
ns = self.namespace.split('/', 2)
xml = r"""<?xml version="1.0" encoding="utf-8"?><CIM CIMVERSION="2.0" DTDVERSION="2.0"><MESSAGE ID="%i" PROTOCOLVERSION="1.0"><SIMPLEREQ><IMETHODCALL NAME="%s">%s%s</IMETHODCALL></SIMPLEREQ></MESSAGE></CIM>"""
imethod = "EnumerateInstances"
assocclass = "<CLASSNAME NAME=\"%s\"/>" % assocclass if assocclass != "" else ""
resultclass = "<CLASSNAME NAME=\"%s\"/>" % resultclass if resultclass != "" else ""
if method == "ei":
ixml = r"""<IPARAMVALUE NAME="ClassName"><CLASSNAME NAME="%s"/></IPARAMVALUE>
<IPARAMVALUE NAME="DeepInheritance"><VALUE>FALSE</VALUE></IPARAMVALUE>
<IPARAMVALUE NAME="LocalOnly"><VALUE>FALSE</VALUE></IPARAMVALUE>
<IPARAMVALUE NAME="IncludeQualifiers"><VALUE>FALSE</VALUE></IPARAMVALUE>
<IPARAMVALUE NAME="IncludeClassOrigin"><VALUE>FALSE</VALUE></IPARAMVALUE>""" % cimclass
elif method == "en":
imethod = "EnumerateInstanceNames"
ixml = "<IPARAMVALUE NAME=\"ClassName\"><CLASSNAME NAME=\"%s\"/></IPARAMVALUE>" % cimclass
elif method == "gi":
imethod = "GetInstance"
ixml = "<IPARAMVALUE NAME=\"InstanceName\"><INSTANCENAME CLASSNAME=\"%s\">%s</INSTANCENAME></IPARAMVALUE>" % (ciminstance['instanceclassname'], self._build_instance_keybindings(ciminstance))
elif method == "as":
imethod = "Associators"
ixml = r"""<IPARAMVALUE NAME="ObjectName"><INSTANCENAME CLASSNAME="%s">%s</INSTANCENAME></IPARAMVALUE>
<IPARAMVALUE NAME="AssocClass">%s</IPARAMVALUE>
<IPARAMVALUE NAME="ResultClass">%s</IPARAMVALUE>""" % (ciminstance['instanceclassname'], self._build_instance_keybindings(ciminstance), assocclass, resultclass)
elif method == "an":
imethod = "AssociatorNames"
ixml = r"""<IPARAMVALUE NAME="ObjectName"><INSTANCENAME CLASSNAME="%s">%s</INSTANCENAME></IPARAMVALUE>
<IPARAMVALUE NAME="AssocClass">%s</IPARAMVALUE>
<IPARAMVALUE NAME="ResultClass">%s</IPARAMVALUE>""" % (ciminstance['instanceclassname'], self._build_instance_keybindings(ciminstance), assocclass, resultclass)
else:
raise Exception("Wrong CIM method")
return (imethod, xml % (msgid, imethod, self._get_localnamespacepath(), ixml))
def _cim_invoke(self, method, cimclass, ciminstance=None, assocclass="", resultclass=""):
msgid = randint(1000, 99999) if self.check_mid else 0
(imethod, xml) = self._build_message(msgid, method, cimclass, ciminstance, assocclass, resultclass)
headers = { 'Content-Type': 'application/xml;charset="UTF-8"', 'CIMProtocolVersion': '1.0', 'CIMOperation': 'MethodCall', 'CIMMethod': imethod, 'CIMObject': self.namespace }
handler = urllib2.urlopen(urllib2.Request(self.url, xml, headers), timeout = 15)
cimxml = et.fromstring(handler.read())[0]
if cimxml.tag == 'MESSAGE' and (not self.check_mid or cimxml.attrib['ID'] == str(msgid)):
resp = cimxml.find('.//IMETHODRESPONSE')
result = []
for error in cimxml.findall('.//ERROR'):
raise Exception(error.attrib['DESCRIPTION'])
if method == "ei" or method == "as":
nodes = './/VALUE.NAMEDINSTANCE'
if method == "as":
nodes = './/VALUE.OBJECTWITHPATH'
for namedinst in resp.findall(nodes):
iresult = {}
iresult['keyinstancenames'] = self._get_instance_keybindings(None, namedinst)
self._get_instance_properties(iresult, namedinst.find('.//INSTANCE'))
result.append(iresult)
elif method == "en" or method == "an":
for inst in resp.findall('.//INSTANCENAME'):
iresult = self._get_instance_keybindings(inst.attrib["CLASSNAME"], inst)
result.append(iresult)
elif method == "gi":
for inst in resp.findall('.//INSTANCE'):
iresult = {}
iresult['keyinstancenames'] = ciminstance
self._get_instance_properties(iresult, inst)
result.append(iresult)
return result
raise Exception("%s: Bad CIMOM answer" % imethod)
def _invoke(self, method, cimclass, ciminstance=None, assocclass="", resultclass="", nothrow=False):
try:
elist = self._cim_invoke(method, cimclass, ciminstance, assocclass, resultclass)
except Exception as e:
if nothrow: return None
msg = '110 CIM error %s' % e
if method == "ei": msg = '110 CIM error when enumerating instance %s: %s' % (cimclass, e)
if method == "en": msg = '110 CIM error when enumerating instance name %s: %s' % (cimclass, e)
if method == "gi": msg = '110 CIM error when getting instance of class %s: %s' % (ciminstance['instanceclassname'], e)
if method == "as": msg = '110 CIM error when getting associators of class %s: %s' % (ciminstance['instanceclassname'], e)
if method == "an": msg = '110 CIM error when getting associator names of class %s: %s' % (ciminstance['instanceclassname'], e)
self.scom.log.scom_alert(SCOM_ERROR, msg)
self.scom.output_error(2, msg) # only ServerView Health State component
exit(110)
return elist
def enumerate_instances(self, cimclass, nothrow=False):
return self._invoke("ei", cimclass, None, "", "", nothrow)
def enumerate_instance_names(self, cimclass, nothrow=False):
return self._invoke("en", cimclass, None, "", "", nothrow)
def get_instance(self, ciminstance, nothrow=False):
return self._invoke("gi", None, ciminstance, "", "", nothrow)
def associators(self, ciminstance, assocclass='', resultclass='', nothrow=False):
return self._invoke("as", None, ciminstance, assocclass, resultclass, nothrow)
def associator_names(self, ciminstance, assocclass='', resultclass='', nothrow=False):
return self._invoke("an", None, ciminstance, assocclass, resultclass, nothrow)
class SNMPClient:
def __init__(self, log, username, password, community_string, host, from_cache=False):
self.log = log
self.community_string = community_string
self.invoke_string = "-v3 -a MD5 -A '%s' -l authNoPriv -u %s " % (password, username)
self.username = username
self.password = password
self.host = host
self.cdf_file = log.homedir + "monitoring.cache"
self.cdf_array = [None] * 2
self.prepare_from_cache() if from_cache else self.prepare()
self.enabled = self.cdf_array[0]
def prepare(self):
self.log.debug('Checking if snmp is enabled')
if self.community_string == '' or self.community_string is None:
self.log.debug('Empty SNMP community string, using default')
self.community_string = DEF_COMMSTRING
self.log.variable('SNMPCommunity', self.community_string)
self.cdf_array[0] = False
if int(commands.getoutput('netstat -nlu | grep ":161" | wc -l')) != 0:
# check v3
if int(commands.getoutput("snmpget -v3 -a MD5 -A '%s' -l authNoPriv -u %s %s %s 2>/dev/null | wc -l" % (self.password, self.username, self.host, SNMP_TEST_OID))) > 0:
self.invoke_string = "-v3 -a MD5 -A '%s' -l authNoPriv -u %s " % (self.password, self.username)
self.log.variable('SNMPVersion', '3')
self.cdf_array[1] = 3
self.cdf_array[0] = True
# check v2
elif int(commands.getoutput("snmpget -v2c -c%s %s %s 2>/dev/null | wc -l" % (self.community_string, self.host, SNMP_TEST_OID))) > 0:
self.invoke_string = '-v2c -c%s ' % self.community_string
self.log.variable('SNMPVersion', '2c')
self.cdf_array[1] = 2
self.cdf_array[0] = True
# check v1
elif int(commands.getoutput("snmpget -v1 -c%s %s %s 2>/dev/null | wc -l" % (self.community_string, self.host, SNMP_TEST_OID))) > 0:
self.invoke_string = '-v1 -c%s ' % self.community_string
self.log.variable('SNMPVersion', '1')
self.cdf_array[1] = 1
self.cdf_array[0] = True
if self.cdf_array[0]: return
self.log.debug('SNMP is not enabled or unavailable for user "%s" or community string "%s"' % (self.username, self.community_string))
return
def prepare_from_cache(self):
self.load_cache()
if self.community_string == '' or self.community_string is None:
self.log.debug('Empty SNMP community string, using default')
self.community_string = DEF_COMMSTRING
self.log.variable('SNMPCommunity', self.community_string)
if self.cdf_array[0] == True:
if self.cdf_array[1] == 3: #v3
self.invoke_string = "-v3 -a MD5 -A '%s' -l authNoPriv -u %s " % (self.password, self.username)
self.log.variable('SNMPVersion', '3')
self.cdf_array[1] = 3
return
if self.cdf_array[1] == 2: #v2
self.invoke_string = '-v2c -c%s ' % self.community_string
self.log.variable('SNMPVersion', '2c')
self.cdf_array[1] = 2
return
if self.cdf_array[1] == 1: #v1
self.invoke_string = '-v1 -c%s ' % self.community_string
self.log.variable('SNMPVersion', '1')
self.cdf_array[1] = 1
return
self.log.debug('SNMP is not enabled or unavailable. If cached state is wrong put target into maintenance mode in SCOM.')
def save_cache(self):
self.log.debug('Saving SNMP cache data to file')
with open(self.cdf_file, "w") as text_file:
pickle.dump(self.cdf_array, text_file)
def load_cache(self):
self.log.debug('Loading SNMP cache data from file')
if os.path.isfile(self.cdf_file):
with open(self.cdf_file, "r") as text_file:
self.cdf_array = pickle.load(text_file)
def cache_devices(self, component):
self.dev_idxs = []
if component in [components_name[STORAGE], components_name[NETWORK], ALL_COMPONENTS]:
self.dev_idxs = self.get_idx(SNMP_DEVICE_INDEX, SNMP_DEVICE_INDEX_LEN)
def snmp_walk(self, oid):
result = commands.getoutput('snmpwalk -Ob %s%s %s' % (self.invoke_string, self.host, oid))
if not "=" in result:
return [ "" ]
else:
value = result.split('=')[1].strip()
if "No Such Object" in value or "No Such Instance" in value or "Unknown Object" in value or "No more variables" in value or "Error in packet" in value or "Timeout" in value:
return [ "" ]
return result.split("\n")
def snmp_get(self, oid):
result = commands.getoutput('snmpget -Ob %s%s %s' % (self.invoke_string, self.host, oid))
if not "=" in result:
return ""
else:
value = result.split('=')[1].strip()
if "No Such Object" in value or "No Such Instance" in value or "Unknown Object" in value or "No more variables" in value or "Error in packet" in value or "Timeout" in value:
return ""
return result
def get_idx(self, oid, idxlen=1):
result = self.snmp_walk(oid)
idxs = []
for line in result:
if line != '':
idxs.append('.'.join(line.split('=')[0].strip().rsplit('.', idxlen)[1:]).strip())
return idxs
def get_var(self, oid, idx=''):
var = self.snmp_get(oid if idx == '' else (oid + '.' + idx))
if "=" in var:
var = var.split('=')[1].strip()
if "STRING:" in var:
var = var.split('STRING:')[1].strip()
if len(var) > 0 and var[0] == '"':
return var[1:-1]
else:
return var
if "INTEGER:" in var:
return var.split('INTEGER:')[1].strip()
return var
return ""
def get_var_i(self, oid, idx=''):
var = self.get_var(oid, idx)
if "(" in var and ")" in var:
var = var.split('(')[1][:-1]
if var == '':
return 0
try:
return int(var)
except:
return 0
def var_to_str(self, snmp_var):
if snmp_var == '""' or snmp_var == '':
return NOT_AVAIL
return snmp_var
def discover_temperatures():
log.debug('Getting ' + components_list[TEMPERATURE] + ' information')
instance_list = cim.enumerate_instances("SVS_PGYTemperatureSensor")
index = len(instance_list)
component_trace.update(TEMPERATURE, index)
if index > 0:
component_name = "%s: %i" % (components_info[TEMPERATURE], index)
component_info = scom.server.get_notpopulated_components(TEMPERATURE)
log.component_debug(component_name, "")
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.TemperatureSensors']$")
scom.add_healthcollection(components_list[TEMPERATURE], component_name, component_info)
scom.append_line("CRI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.ServerContainsTemperatureSensors']$")
for instance in instance_list:
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.TemperatureSensor']$")
scom.add_hc_componenthealth(scom.get_component_name(-1, instance['elementname'], instance['deviceid']))
def discover_voltages():
log.debug('Getting ' + components_list[VOLTAGES] + ' information')
instance_list = cim.enumerate_instances("SVS_PGYVoltageSensor")
index = len(instance_list)
component_trace.update(VOLTAGES, index)
if index > 0:
component_name = "%s: %i" % (components_info[VOLTAGES], index)
component_info = scom.server.get_notpopulated_components(VOLTAGES)
log.component_debug(component_name, "")
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.VoltageSensors']$")
scom.add_healthcollection(components_list[VOLTAGES], component_name, component_info)
scom.append_line("CRI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.ServerContainsVoltageSensors']$")
for instance in instance_list:
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.VoltageSensor']$")
scom.add_hc_componenthealth(instance['elementname'])
def discover_powersupplies():
log.debug('Getting ' + components_list[POWERSUPPLY] + ' information')
psus = {}
instance_list = cim.enumerate_instances("SVS_PGYPowerSupply")
index = len(instance_list)
for instance in instance_list:
psus[instance['deviceid']] = { 'name': instance['elementname'] }
component_trace.update(POWERSUPPLY, index)
if index > 0:
component_name = "%s: %i" % (components_info[POWERSUPPLY], index)
component_info = scom.server.get_notpopulated_components(POWERSUPPLY)
log.component_debug(component_name, "")
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.PowerSupplies']$")
scom.add_healthcollection(components_list[POWERSUPPLY], component_name, component_info)
scom.append_line("CRI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.ServerContainsPowerSupplies']$")
for key, val in psus.iteritems():
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.PowerSupply']$")
scom.add_hc_componenthealth(scom.get_component_name(-1, psus[key]['name'], key), True)
def discover_powerconsumption():
index, component_info, component_name = 0, "", ""
log.debug('Getting ' + components_list[POWERCONSUMP] + ' information')
instance_list = cim.enumerate_instances("SVS_PGYPowerConsumptionSensor")
for instance in instance_list:
# Info: SV Agents SCCI only supply the 'Total Power' sensor (#E0) with sensible values.
# If 'CurrentState' is unknown power control mode is not set to 'Power Limit'.
if 'e0' in instance['deviceid'].lower() and instance['elementname'] == "Total Power":
component_name += "Power Level"
component_info += "Sensor: %s" % instance['elementname']
index = 1
break
component_trace.update(POWERCONSUMP, index)
if component_name != "":
log.component_debug(component_name, component_info)
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.PowerConsumption']$")
scom.add_healthcollection(components_list[POWERCONSUMP], component_name, component_info)
scom.append_line("CRI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.ServerContainsPowerConsumption']$")
def discover_raid():
def discover_raid_cim():
def get_firmware(controller):
log.debug(" getting firmware version for controller %s" % controller['elementname'])
for portController in portControllers:
if portController['elementname'] == controller['elementname']:
for software in scom.server.softw_identities:
if portController['model'] in software['InstanceID'][1]:
instance = cim.get_instance(software)
if 'firmware' in instance[0]['description'].lower():
return instance[0]['versionstring']
return "Unknown"
def get_physical_disks(controller):
log.debug(" getting physicial disks for controller %s" % controller['elementname'])
disksData = []
cim.timeout = 25
disks = cim.associators(controller['keyinstancenames'], "", "SVS_PGYDiskDrive")
cim.timeout = 15
for disk in disks:
diskData = { 'name': disk['elementname'], 'deviceid': "%s (%s)" % (disk['elementname'], disk['deviceid']) }
size = 0
for extent in diskExtents:
if disk['deviceid'] == extent['deviceid']:
size = int(extent['numberofblocks']) * int(extent['blocksize'])
break
diskData['size'] = size
for physical in physicalDisks:
if disk['deviceid'] == physical['instanceid']:
diskData['firmware'] = physical['firmwareversion']
diskData['model'] = physical['model']
diskData['serial'] = physical['serialnumber']
diskData['vendor'] = physical['manufacturer']
break
size = sizeof_fmt(size)
if size in physical_groups:
physical_groups[size] += 1
else:
physical_groups[size] = 1
disksData.append(diskData)
return disksData
def get_logical_drives(controller):
log.debug(" getting logical drives for controller %s" % controller['elementname'])
drivesData = []
for drive in logicalDrives:
if drive['deviceid'].startswith(controller['name']):
level = cim_raid_levels[int(drive['raidlevel'])]
size = int(drive['numberofblocks']) * int(drive['blocksize'])
discover_raid_cim.total_size += size
driveData = { 'name': drive['elementname'], 'deviceid': "%s (%s)" % (drive['elementname'], drive['deviceid']), 'level': level, 'size': size }
if level in logical_groups:
logical_groups[level] += 1
else:
logical_groups[level] = 1
drivesData.append(driveData)
return drivesData
def add_controller(controller):
return { 'name': controller['elementname'], \
'firmware': get_firmware(controller), \
'logicalDrives': get_logical_drives(controller),\
'physicalDisks': get_physical_disks(controller) }
raidData = { 'avail': False, 'controllers': {} }
if (cimControllers == None):
log.debug('No %s controllers found (CIM).' % components_list[RAIDSUBSYSTEM])
return raidData
portControllers = cim.enumerate_instances("SVS_PGYPortController")
physicalDisks = cim.enumerate_instances("SVS_PGYPhysicalDiskPackage")
diskExtents = cim.enumerate_instances("SVS_PGYDiskExtent")
logicalDrives = cim.enumerate_instances("SVS_PGYStoragePoolCompositeExtent")
log.debug('Processing gathered information (CIM)')
discover_raid_cim.total_size = 0
physical_groups, logical_groups = {}, {}
if len(cimControllers) > 0:
idx = 1
for controller in cimControllers:
raidData['controllers'][str(idx)] = add_controller(controller)
idx += 1
log.debug('Adding info for ' + components_list[RAIDSUBSYSTEM])
raidData['lCount'] = len(logicalDrives)
raidData['pCount'] = len(physicalDisks)
raidData['name'] = "%s: %i" % (components_info[RAIDSUBSYSTEM], len(cimControllers))
raidData['info'] = "Logical Drives: %s, %s; Physical Disks: %s, %s" % (raidData['lCount'], print_dict(logical_groups), raidData['pCount'], print_dict(physical_groups))
raidData['totalSize'] = sizeof_fmt(discover_raid_cim.total_size)
raidData['avail'] = True
return raidData
def discover_raid_snmp():
def prepare_controllers():
controllers = {}
idxs = snmp.get_idx(SNMP_CONTROL_CTRLNR, SNMP_CONTROL_INDEX_LEN)
for idx in idxs:
name = snmp.get_var(SNMP_CONTROL_DESCR, idx)
info = snmp.get_var(SNMP_CONTROL_FIRMWARE_REV, idx)
if name == "": break
if info == '""': info = ''
controllers[idx] = { 'name': name, 'firmware': info, 'physicalDisks': [], 'logicalDrives': [] }
return controllers
def add_item_to_controller(controller, node, data):
for item in raidData['controllers']:
if item == controller:
raidData['controllers'][item][node].append(data)
def count_controllers_node(node):
count = 0
for controller in raidData['controllers']:
for item in raidData['controllers'][controller][node]:
count += 1
return count
def get_physical_disks():
log.debug(' getting ' + components_list[PHYSICALDISK] + ' information')
idxs = snmp.get_idx(SNMP_PHYS_DEV_CTRLNR, SNMP_PHYS_DEV_INDEX_LEN)
controller, last_controller = 0, 0
if len(idxs) > 0:
last_controller = idxs[0].split('.')[0]
for idx in idxs:
controller = idx.split('.')[0]
if last_controller != controller:
last_controller = controller
if not controller in raidData['controllers']: continue
name = snmp.get_var(SNMP_PHYS_DEV_DESCR, idx)
if name == "": break
diskData = { 'name': name, 'deviceid': add_controller_number(controller, name), \
'size': snmp.get_var_i(SNMP_PHYS_DEV_CAPACITY, idx) * 1024 * 1024, \
'vendor': snmp.var_to_str(snmp.get_var(SNMP_PHYS_DEV_VENDOR, idx)), \
'model': snmp.var_to_str(snmp.get_var(SNMP_PHYS_DEV_MODEL, idx)), \
'serial': snmp.var_to_str(snmp.get_var(SNMP_PHYS_DEV_SERIALNUM, idx)),\
'firmware': snmp.var_to_str(snmp.get_var(SNMP_PHYS_DEV_FIRMWARE, idx)) }
add_item_to_controller(controller, 'physicalDisks', diskData)
size = sizeof_fmt(diskData['size'])
if size in physical_groups:
physical_groups[size] += 1
else:
physical_groups[size] = 1
def get_logical_drives():
log.debug(' getting ' + components_list[LOGICALDRIVE] + ' information')
idxs = snmp.get_idx(SNMP_LOG_DRV_CTRLNR, SNMP_LOG_DRV_INDEX_LEN)
controller, last_controller = 0, 0
if len(idxs) > 0:
last_controller = idxs[0].split('.')[0]
for idx in idxs:
controller = idx.split('.')[0]
if last_controller != controller:
last_controller = controller
if not controller in raidData['controllers']: continue
name = snmp.get_var(SNMP_LOG_DRV_NAME, idx)
if name == "": break
level = snmp.get_var(SNMP_LOG_DRV_RAID_LVL_STR, idx)
driveData = { 'name': name, 'deviceid': add_controller_number(controller, name), \
'size': snmp.get_var_i(SNMP_LOG_DRV_ARRAYSIZE, idx) * 1024 * 1024, \
'level': level }
add_item_to_controller(controller, 'logicalDrives', driveData)
discover_raid_snmp.total_size += driveData['size']
if level in logical_groups:
logical_groups[level] += 1
else:
logical_groups[level] = 1
raidData = {'avail': False, 'controllers': prepare_controllers()}
discover_raid_snmp.total_size = 0
if len(raidData['controllers']) == 0:
log.debug('No %s controllers found (SNMP).' % components_list[RAIDSUBSYSTEM])
else:
physical_groups, logical_groups = {}, {}
get_physical_disks()
get_logical_drives()
raidData['lCount'] = count_controllers_node('logicalDrives')
raidData['pCount'] = count_controllers_node('physicalDisks')
raidData['name'] = "%s: %i" % (components_info[RAIDSUBSYSTEM], len(raidData['controllers']))
raidData['info'] = "Logical Drives: %s, %s; Physical Disks: %s, %s" % (raidData['lCount'], print_dict(logical_groups), raidData['pCount'], print_dict(physical_groups))
raidData['totalSize'] = sizeof_fmt(discover_raid_snmp.total_size)
raidData['avail'] = True
return raidData
def publish_raid_data(data):
# RAID Components
# -----------------------------------------------------------------------
log.debug('Creating instance of ' + components_list[RAIDSUBSYSTEM])
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.RaidComponents']$")
scom.add_healthcollection(components_list[RAIDSUBSYSTEM], data['name'], data['info'])
scom.append_line("CRI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.ServerContainsRaid']$")
# RAID Overall Status
# -----------------------------------------------------------------------
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.SVRaidOverallState']$")
scom.add_hc_componenthealth("ServerView RAID Overall State", True)
for idx in data['controllers']:
controller = data['controllers'][idx]
# RAID Controller
# -----------------------------------------------------------------------
log.component_debug(controller['name'], controller['firmware'])
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.RaidController']$")
scom.add_hc_controllercollection(controller['name'], False)
scom.append_line("AP $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.RaidController']/Firmware$ %s" % controller['firmware'])
scom.append_line("ADDC")
if len(controller['physicalDisks']) > 0:
scom.add_physical_drives(controller['name'])
for disk in controller['physicalDisks']:
# RAID Physical Disk
# ---------------------------------------------------------------------------
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.RaidPhysicalDisk']$")
scom.add_hc_componenthealth(disk['deviceid'], False, disk['name'])
scom.append_line("AP $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.ControllerHealthCollection']/Device$ %s" % controller['name'])
scom.append_line("AP $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.SimpleCollection']/NetworkName$ %s" % network_name)
scom.append_line("AP $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.RaidPhysicalDisk']/Size$ %s" % sizeof_fmt(disk['size']))
scom.append_line("AP $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.RaidPhysicalDisk']/FirmwareRevision$ %s" % disk['firmware'])
scom.append_line("AP $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.RaidPhysicalDisk']/ModelName$ %s" % disk['model'])
scom.append_line("AP $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.RaidPhysicalDisk']/SerialNumber$ %s" % disk['serial'])
scom.append_line("AP $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.RaidPhysicalDisk']/VendorName$ %s" % disk['vendor'])
scom.append_line("ADDC")
if len(controller['logicalDrives']) > 0:
scom.add_logical_drives(controller['name'])
for drive in controller['logicalDrives']:
# RAID Logical Drive
# ---------------------------------------------------------------------------
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.RaidLogicalDrive']$")
scom.add_hc_componenthealth(drive['deviceid'], False, drive['name'])
scom.append_line("AP $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.ControllerHealthCollection']/Device$ %s" % controller['name'])
scom.append_line("AP $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.SimpleCollection']/NetworkName$ %s" % network_name)
scom.append_line("AP $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.RaidLogicalDrive']/Size$ %s" % sizeof_fmt(drive['size']))
scom.append_line("AP $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.RaidLogicalDrive']/Level$ %s" % drive['level'])
scom.append_line("ADDC")
log.debug('Getting ' + components_list[RAIDSUBSYSTEM] + ' information')
if scom.server.raid_ver < MIN_RD_VER:
log.debug('%s version (%s) too low. Min supported version is %s.' % (components_list[RAIDSUBSYSTEM], scom.server.raid_ver, MIN_RD_VER))
return
cimControllers = cim.enumerate_instances("SVS_PGYHostRaidController", True)
if cimControllers == None and snmp.enabled:
log.debug(' using SNMP to gather RAID info')
data = discover_raid_snmp()
else:
log.debug(' using CIM to gather RAID info')
data = discover_raid_cim()
if data['avail']:
publish_raid_data(data)
component_trace.update(RAIDSUBSYSTEM, len(data['controllers']))
component_trace.update(PHYSICALDISK, data['pCount'])
component_trace.update(LOGICALDRIVE, data['lCount'])
else:
component_trace.update(RAIDSUBSYSTEM, 0)
component_trace.update(PHYSICALDISK, 0)
component_trace.update(LOGICALDRIVE, 0)
def discover_networks(): # SNMP
network_devices = {}
if snmp.enabled:
log.debug('Getting ' + components_list[NETWORK] + ' information')
idxs = snmp.get_idx(SNMP_NET_IF_INDEX, SNMP_NET_IF_INDEX_LEN)
for idx in idxs:
if 'ether' in snmp.get_var(SNMP_NET_IF_TYPE, idx).lower():
name = snmp.get_var(SNMP_NET_IF_DESCR, idx)
if name == '': continue
network_devices[name] = snmp.get_var(SNMP_NET_IF_PHYS_ADDR, idx)
index = len(network_devices)
component_trace.update(NETWORK, index)
if index > 0:
component_name = "%s: %i" % (components_info[NETWORK], index)
log.component_debug(component_name, "")
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.ServerNetworks']$")
scom.add_healthcollection(components_list[NETWORK], component_name, "")
scom.append_line("CRI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.ServerContainsServerNetworks']$")
for name, val in network_devices.iteritems():
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.NetworkDevice']$")
scom.add_hc_componenthealth(name, False)
scom.append_line("AP $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.NetworkDevice']/MACAddress$ %s" % val)
scom.append_line("ADDC")
def discover_storage(): # SNMP
index, component_info, component_name = 0, "", ""
storage_disks, storage_groups = {}, {}
if snmp.enabled:
log.debug('Getting ' + components_list[STORAGE] + ' information')
total_size = 0
idxs = snmp.get_idx(SNMP_DEVICE_INDEX, SNMP_DEVICE_INDEX_LEN)
for idx in idxs:
if 'diskstorage' in snmp.get_var(SNMP_DEVICE_TYPE, idx).lower():
name = snmp.get_var(SNMP_DEVICE_DESCR, idx)
try:
size = int(snmp.get_var(SNMP_DEVICE_SIZE, idx).split(' ')[0]) * 1024
except:
size = 0
total_size += size
info = sizeof_fmt(size)
storage_disks[name] = { 'info': info, 'size': size }
if name in storage_groups:
storage_groups[info] += 1
else:
storage_groups[info] = 1
index += 1
component_name = "%s: %i" % (components_info[STORAGE], index)
if total_size > 0:
disksize_total = sizeof_fmt(total_size)
component_info = "Overall Disk Space: %s; %s" % (disksize_total, print_dict(storage_groups))
scom.server.disksize_total = disksize_total
component_trace.update(STORAGE, index)
if index != 0:
log.component_debug(component_name, component_info)
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.ServerStorage']$")
scom.add_healthcollection(components_list[STORAGE], component_name, component_info)
scom.append_line("CRI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.ServerContainsServerStorage']$")
for name, disk in storage_disks.iteritems():
scom.append_line("CCI $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.StorageDisk']$")
scom.add_hc_componenthealth(name, False)
scom.append_line("AP $MPElement[Name='Fujitsu.Servers.PRIMERGY.Linux.StorageDisk']/Size$ %s" % disk['info'])
scom.append_line("ADDC")
# check std out
if ($StdOut.Length -le 0) {
if ($StdErr.Length -gt 0) {
$Logger.Error(107, "Error: Empty data returned from Linux Server $($PrincipalName). StdErr: $($StdErr).")
} else {
$Logger.Error(107, "Error: Empty data returned from Linux Server $($PrincipalName).")
}
$oDiscoveryEmptyData.IsSnapshot = $False # do not discard existing discovery data
$oDiscoveryEmptyData
exit 107
}
if (($ReturnCode -ne 0) -and (! (CheckReturnCode $ReturnCode $PrincipalName))) {
if (! ($ReturnCode -in @(109, 113, 114))) { # do not discard existing discovery data if return code != 109, 113, 114 (see: CheckReturnCode)
$oDiscoveryEmptyData.IsSnapshot = $False
}
$oDiscoveryEmptyData
exit $ReturnCode
}
# process all lines of output
try {
$lines = Expand-GZip $StdOut
$lines -Split "`n" | ForEach-Object {
$array = $_.Trim() -Split " ", 3
$Logger.Debug("***** Normal end of script. *****")
}
function CheckReturnCode {
param (
[int] $ReturnCode,
[string] $TargetComputer
)
[bool]$Result = $True
switch ($ReturnCode)
{
108 { $Logger.Error($ReturnCode, "Error: Cannot prepare connection to CIMOM"); break }
109 { $Logger.Debug("**** The ServerView Agent is not installed on PRIMERGY Linux Server $TargetComputer ****"); $Result = $False; break }
110 { $Logger.Error($ReturnCode, "Error: Cannot enumerate CIM instance"); break }
111 { $Logger.Error($ReturnCode, "Error: The ServerView Agent is not running on PRIMERGY Linux Server $TargetComputer."); break }
112 { $Logger.Error($ReturnCode, "Error: The ServerView Agent version is too old on PRIMERGY Linux Server $TargetComputer."); break }
113 { $Logger.Debug("**** Not a Fujitsu PRIMERGY Linux Server ****"); $Result = $False; break }
114 { $Logger.Debug("**** Not a system of Fujitsu ****"); $Result = $False; break }
default { $Logger.Debug("Unknown error"); $Result = $False; break }
}