File: //proc/self/root/usr/lib/python2.7/site-packages/salt/modules/solaris_fmadm.py
# -*- coding: utf-8 -*-
'''
Module for running fmadm and fmdump on Solaris
:maintainer: Jorge Schrauwen <sjorge@blackdot.be>
:maturity: new
:platform: solaris,illumos
.. versionadded:: 2016.3.0
'''
from __future__ import absolute_import, unicode_literals, print_function
# Import Python libs
import logging
# Import Salt libs
import salt.utils.path
import salt.utils.platform
import salt.utils.decorators as decorators
from salt.utils.odict import OrderedDict
log = logging.getLogger(__name__)
# Function aliases
__func_alias__ = {
'list_records': 'list',
}
# Define the module's virtual name
__virtualname__ = 'fmadm'
@decorators.memoize
def _check_fmadm():
'''
Looks to see if fmadm is present on the system
'''
return salt.utils.path.which('fmadm')
def _check_fmdump():
'''
Looks to see if fmdump is present on the system
'''
return salt.utils.path.which('fmdump')
def __virtual__():
'''
Provides fmadm only on Solaris
'''
if salt.utils.platform.is_sunos() and \
_check_fmadm() and _check_fmdump():
return __virtualname__
return (
False,
'{0} module can only be loaded on Solaris with the fault management installed'.format(
__virtualname__
)
)
def _parse_fmdump(output):
'''
Parses fmdump output
'''
result = []
output = output.split("\n")
# extract header
header = [field for field in output[0].lower().split(" ") if field]
del output[0]
# parse entries
for entry in output:
entry = [item for item in entry.split(" ") if item]
entry = ['{0} {1} {2}'.format(entry[0], entry[1], entry[2])] + entry[3:]
# prepare faults
fault = OrderedDict()
for field in header:
fault[field] = entry[header.index(field)]
result.append(fault)
return result
def _parse_fmdump_verbose(output):
'''
Parses fmdump verbose output
'''
result = []
output = output.split("\n")
fault = []
verbose_fault = {}
for line in output:
if line.startswith('TIME'):
fault.append(line)
if len(verbose_fault) > 0:
result.append(verbose_fault)
verbose_fault = {}
elif len(fault) == 1:
fault.append(line)
verbose_fault = _parse_fmdump("\n".join(fault))[0]
fault = []
elif len(verbose_fault) > 0:
if 'details' not in verbose_fault:
verbose_fault['details'] = ""
if line.strip() == '':
continue
verbose_fault['details'] = '{0}{1}\n'.format(
verbose_fault['details'],
line
)
if len(verbose_fault) > 0:
result.append(verbose_fault)
return result
def _parse_fmadm_config(output):
'''
Parsbb fmdump/fmadm output
'''
result = []
output = output.split("\n")
# extract header
header = [field for field in output[0].lower().split(" ") if field]
del output[0]
# parse entries
for entry in output:
entry = [item for item in entry.split(" ") if item]
entry = entry[0:3] + [" ".join(entry[3:])]
# prepare component
component = OrderedDict()
for field in header:
component[field] = entry[header.index(field)]
result.append(component)
# keying
keyed_result = OrderedDict()
for component in result:
keyed_result[component['module']] = component
del keyed_result[component['module']]['module']
result = keyed_result
return result
def _fmadm_action_fmri(action, fmri):
'''
Internal function for fmadm.repqired, fmadm.replaced, fmadm.flush
'''
ret = {}
fmadm = _check_fmadm()
cmd = '{cmd} {action} {fmri}'.format(
cmd=fmadm,
action=action,
fmri=fmri
)
res = __salt__['cmd.run_all'](cmd)
retcode = res['retcode']
result = {}
if retcode != 0:
result['Error'] = res['stderr']
else:
result = True
return result
def _parse_fmadm_faulty(output):
'''
Parse fmadm faulty output
'''
def _merge_data(summary, fault):
result = {}
uuid = summary['event-id']
del summary['event-id']
result[uuid] = OrderedDict()
result[uuid]['summary'] = summary
result[uuid]['fault'] = fault
return result
result = {}
summary = []
summary_data = {}
fault_data = {}
data_key = None
for line in output.split("\n"):
# we hit a divider
if line.startswith('-'):
if summary and summary_data and fault_data:
# we have data, store it and reset
result.update(_merge_data(summary_data, fault_data))
summary = []
summary_data = {}
fault_data = {}
continue
else:
# we don't have all data, colelct more
continue
# if we do not have the header, store it
if not summary:
summary.append(line)
continue
# if we have the header but no data, store the data and parse it
if summary and not summary_data:
summary.append(line)
summary_data = _parse_fmdump("\n".join(summary))[0]
continue
# if we have a header and data, assume the other lines are details
if summary and summary_data:
# if line starts with a whitespace and we already have a key, append
if line.startswith(' ') and data_key:
fault_data[data_key] = "{0}\n{1}".format(
fault_data[data_key],
line.strip()
)
# we have a key : value line, parse it
elif ':' in line:
line = line.split(':')
data_key = line[0].strip()
fault_data[data_key] = ":".join(line[1:]).strip()
# note: for some reason Chassis_id is lobbed ofter Platform, fix that here
if data_key == 'Platform':
fault_data['Chassis_id'] = fault_data[data_key][fault_data[data_key].index('Chassis_id'):].split(':')[-1].strip()
fault_data[data_key] = fault_data[data_key][0:fault_data[data_key].index('Chassis_id')].strip()
# we have data, store it and reset
result.update(_merge_data(summary_data, fault_data))
return result
def list_records(after=None, before=None):
'''
Display fault management logs
after : string
filter events after time, see man fmdump for format
before : string
filter events before time, see man fmdump for format
CLI Example:
.. code-block:: bash
salt '*' fmadm.list
'''
ret = {}
fmdump = _check_fmdump()
cmd = '{cmd}{after}{before}'.format(
cmd=fmdump,
after=' -t {0}'.format(after) if after else '',
before=' -T {0}'.format(before) if before else ''
)
res = __salt__['cmd.run_all'](cmd)
retcode = res['retcode']
result = {}
if retcode != 0:
result['Error'] = 'error executing fmdump'
else:
result = _parse_fmdump(res['stdout'])
return result
def show(uuid):
'''
Display log details
uuid: string
uuid of fault
CLI Example:
.. code-block:: bash
salt '*' fmadm.show 11b4070f-4358-62fa-9e1e-998f485977e1
'''
ret = {}
fmdump = _check_fmdump()
cmd = '{cmd} -u {uuid} -V'.format(
cmd=fmdump,
uuid=uuid
)
res = __salt__['cmd.run_all'](cmd)
retcode = res['retcode']
result = {}
if retcode != 0:
result['Error'] = 'error executing fmdump'
else:
result = _parse_fmdump_verbose(res['stdout'])
return result
def config():
'''
Display fault manager configuration
CLI Example:
.. code-block:: bash
salt '*' fmadm.config
'''
ret = {}
fmadm = _check_fmadm()
cmd = '{cmd} config'.format(
cmd=fmadm
)
res = __salt__['cmd.run_all'](cmd)
retcode = res['retcode']
result = {}
if retcode != 0:
result['Error'] = 'error executing fmadm config'
else:
result = _parse_fmadm_config(res['stdout'])
return result
def load(path):
'''
Load specified fault manager module
path: string
path of fault manager module
CLI Example:
.. code-block:: bash
salt '*' fmadm.load /module/path
'''
ret = {}
fmadm = _check_fmadm()
cmd = '{cmd} load {path}'.format(
cmd=fmadm,
path=path
)
res = __salt__['cmd.run_all'](cmd)
retcode = res['retcode']
result = {}
if retcode != 0:
result['Error'] = res['stderr']
else:
result = True
return result
def unload(module):
'''
Unload specified fault manager module
module: string
module to unload
CLI Example:
.. code-block:: bash
salt '*' fmadm.unload software-response
'''
ret = {}
fmadm = _check_fmadm()
cmd = '{cmd} unload {module}'.format(
cmd=fmadm,
module=module
)
res = __salt__['cmd.run_all'](cmd)
retcode = res['retcode']
result = {}
if retcode != 0:
result['Error'] = res['stderr']
else:
result = True
return result
def reset(module, serd=None):
'''
Reset module or sub-component
module: string
module to unload
serd : string
serd sub module
CLI Example:
.. code-block:: bash
salt '*' fmadm.reset software-response
'''
ret = {}
fmadm = _check_fmadm()
cmd = '{cmd} reset {serd}{module}'.format(
cmd=fmadm,
serd='-s {0} '.format(serd) if serd else '',
module=module
)
res = __salt__['cmd.run_all'](cmd)
retcode = res['retcode']
result = {}
if retcode != 0:
result['Error'] = res['stderr']
else:
result = True
return result
def flush(fmri):
'''
Flush cached state for resource
fmri: string
fmri
CLI Example:
.. code-block:: bash
salt '*' fmadm.flush fmri
'''
return _fmadm_action_fmri('flush', fmri)
def repaired(fmri):
'''
Notify fault manager that resource has been repaired
fmri: string
fmri
CLI Example:
.. code-block:: bash
salt '*' fmadm.repaired fmri
'''
return _fmadm_action_fmri('repaired', fmri)
def replaced(fmri):
'''
Notify fault manager that resource has been replaced
fmri: string
fmri
CLI Example:
.. code-block:: bash
salt '*' fmadm.repaired fmri
'''
return _fmadm_action_fmri('replaced', fmri)
def acquit(fmri):
'''
Acquit resource or acquit case
fmri: string
fmri or uuid
CLI Example:
.. code-block:: bash
salt '*' fmadm.acquit fmri | uuid
'''
return _fmadm_action_fmri('acquit', fmri)
def faulty():
'''
Display list of faulty resources
CLI Example:
.. code-block:: bash
salt '*' fmadm.faulty
'''
fmadm = _check_fmadm()
cmd = '{cmd} faulty'.format(
cmd=fmadm,
)
res = __salt__['cmd.run_all'](cmd)
result = {}
if res['stdout'] == '':
result = False
else:
result = _parse_fmadm_faulty(res['stdout'])
return result
def healthy():
'''
Return whether fmadm is reporting faults
CLI Example:
.. code-block:: bash
salt '*' fmadm.healthy
'''
return False if faulty() else True
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4