Volans has uploaded a new change for review.
https://gerrit.wikimedia.org/r/322249
Change subject: RAID: get megacli status of physical disks too
......................................................................
RAID: get megacli status of physical disks too
- add support to get the status of the physical disks (with the -p flag)
instead of the logical drives (the default)
Bug: T151043
Change-Id: Idde1b95a2112de6badf029d911e160882ee54af2
---
M modules/raid/files/get-raid-status-megacli.py
1 file changed, 84 insertions(+), 23 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/operations/puppet
refs/changes/49/322249/1
diff --git a/modules/raid/files/get-raid-status-megacli.py
b/modules/raid/files/get-raid-status-megacli.py
index 7164f26..efcb699 100644
--- a/modules/raid/files/get-raid-status-megacli.py
+++ b/modules/raid/files/get-raid-status-megacli.py
@@ -14,11 +14,12 @@
EXIT_LINE_STARTSWITH = 'Exit Code:'
# Hierarchically ordered contexts
-ORDERED_CONTEXTS = ('raw_disk', 'physical_drive', 'span', 'virtual_drive',
- 'adapter')
+ORDERED_LOGICAL_CONTEXTS = (
+ 'raw_disk', 'physical_drive', 'span', 'virtual_drive', 'adapter')
+ORDERED_PHYSICAL_CONTEXTS = ('raw_disk', 'enclosure', 'adapter')
# Rules on how to interpret the megacli output and how to do the summary
-CONTEXTS = {
+LOGICAL_CONTEXTS = {
'adapter': {
'parent': None,
'include_childs': False,
@@ -28,7 +29,7 @@
'virtual_drive': {
'parent': 'adapter',
'include_childs': False,
- 'optimal_values': {'State': 'Optimal'},
+ 'optimal_values': {'State': ['Optimal']},
'print_keys': (
'Virtual Drive',
'RAID Level',
@@ -49,10 +50,10 @@
'parent': 'span',
'include_childs': True,
'optimal_values': {
- 'Media Error Count': '0',
- 'Other Error Count': '0',
- 'Predictive Failure Count': '0',
- 'Last Predictive Failure Event Seq Number': '0',
+ 'Media Error Count': ['0'],
+ 'Other Error Count': ['0'],
+ 'Predictive Failure Count': ['0'],
+ 'Last Predictive Failure Event Seq Number': ['0'],
},
'print_keys': (
'PD',
@@ -68,7 +69,7 @@
'raw_disk': {
'parent': 'physical_drive',
'include_childs': False,
- 'optimal_values': {'Firmware state': 'Online, Spun Up'},
+ 'optimal_values': {'Firmware state': ['Online, Spun Up']},
'print_keys': (
'Raw Size',
'Firmware state',
@@ -78,6 +79,47 @@
}
}
+PHYSICAL_CONTEXTS = {
+ 'adapter': {
+ 'parent': None,
+ 'include_childs': False,
+ 'optimal_values': {},
+ 'print_keys': ('name', ),
+ },
+ 'enclosure': {
+ 'parent': 'adapter',
+ 'include_childs': True,
+ 'optimal_values': {
+ 'Media Error Count': ['0'],
+ 'Other Error Count': ['0'],
+ 'Predictive Failure Count': ['0'],
+ 'Last Predictive Failure Event Seq Number': ['0'],
+ },
+ 'print_keys': (
+ 'Enclosure Device ID',
+ 'Slot Number',
+ 'Enclosure position',
+ 'Device Id',
+ 'Media Error Count',
+ 'Other Error Count',
+ 'Predictive Failure Count',
+ 'Last Predictive Failure Event Seq Number',
+ ),
+ },
+ 'raw_disk': {
+ 'parent': 'enclosure',
+ 'include_childs': False,
+ 'optimal_values': {'Firmware state': ['JBOD', 'Online, Spun Up']},
+ 'print_keys': (
+ 'Raw Size',
+ 'Firmware state',
+ 'Media Type',
+ 'Drive Temperature',
+ ),
+ }
+}
+
+
# Keys that determines the change of context from one block to the next one
KEY_TO_CONTEXT = {
'Adapter': 'adapter',
@@ -85,13 +127,14 @@
'Span': 'span',
'PD': 'physical_drive',
'Raw Size': 'raw_disk',
+ 'Enclosure Device ID': 'enclosure',
}
class RaidStatus():
"""Representation of a RAID status with all it's components"""
- def __init__(self):
+ def __init__(self, get_physical=False):
"""Class constructor"""
self.adapters = [] # There can be multiple adapters
self.current_context = None # Pointer to the current context
@@ -102,6 +145,15 @@
self.span = None
self.physical_drive = None
self.raw_disk = None
+ self.enclosure = None
+
+ self.get_physical = get_physical
+ if get_physical:
+ self.contexts = PHYSICAL_CONTEXTS
+ self.ordered_contexts = ORDERED_PHYSICAL_CONTEXTS
+ else:
+ self.contexts = LOGICAL_CONTEXTS
+ self.ordered_contexts = ORDERED_LOGICAL_CONTEXTS
def add_block(self, context, key, value):
""" Initialize a new block and move it's related pointer
@@ -112,7 +164,7 @@
value -- the value to be added to the new block for the given key
"""
- self.consolidate(context)
+ self.consolidate(final_context=context)
setattr(self, context, {
'context': context,
'optimal': True,
@@ -136,9 +188,9 @@
self.current_context[key] = value
context_name = self.current_context['context']
- optimal_values = CONTEXTS[context_name]['optimal_values']
+ optimal_values = self.contexts[context_name]['optimal_values']
- if key in optimal_values.keys() and optimal_values[key] != value:
+ if key in optimal_values.keys() and value not in optimal_values[key]:
self.current_context['optimal'] = False
sep = '====='
self.current_context[key] = '{}> {} <{}'.format(
@@ -146,10 +198,10 @@
# Mark as non optimal the whole parent chain
while True:
- if CONTEXTS[context_name]['parent'] is None:
+ if self.contexts[context_name]['parent'] is None:
break
- parent = getattr(self, CONTEXTS[context_name]['parent'])
+ parent = getattr(self, self.contexts[context_name]['parent'])
parent['optimal'] = False
context_name = parent['context']
@@ -160,9 +212,9 @@
final_context -- the name of the context up to which consolidate
"""
- for context in ORDERED_CONTEXTS:
+ for context in self.ordered_contexts:
block = getattr(self, context)
- parent_context = CONTEXTS[context]['parent']
+ parent_context = self.contexts[context]['parent']
# End of parents chain reached
if parent_context is None:
@@ -216,7 +268,7 @@
"""
status = []
- for key in CONTEXTS[block['context']]['print_keys']:
+ for key in self.contexts[block['context']]['print_keys']:
try:
status.append('{}{}: {}'.format(prefix, key, block[key]))
except:
@@ -228,7 +280,7 @@
# Skip the child if not needed
if not get_all and child['optimal']:
if (block['optimal'] or
- not CONTEXTS[block['context']]['include_childs']):
+ not self.contexts[block['context']]['include_childs']):
continue
status += self._get_block_status(
@@ -248,7 +300,11 @@
help='Compress with zlib the summary to overcome NRPE output limits.')
parser.add_argument(
'-a', dest='all', action='store_true',
- help='Include all components in the summary.')
+ help='Include all components in the summary, not only failing ones.')
+ parser.add_argument(
+ '-p', '--physical', action='store_true',
+ help=('Get the status of the physical drives, by default logical ones'
+ 'are checked.'))
return parser.parse_args()
@@ -260,8 +316,12 @@
status -- a RaidStatus instance
"""
- try:
+ if status.get_physical:
+ command = ['/usr/sbin/megacli', '-PDList', '-aAll']
+ else:
command = ['/usr/sbin/megacli', '-LdPdInfo', '-aAll']
+
+ try:
proc = subprocess.Popen(command, stdout=subprocess.PIPE)
except:
print('Unable to run: {}'.format(command))
@@ -294,7 +354,8 @@
key, value = [el.strip(' \t\r\n') for el in line.split(':', 1)]
- if key in KEY_TO_CONTEXT.keys():
+ if (key in KEY_TO_CONTEXT.keys() and
+ KEY_TO_CONTEXT[key] in status.contexts.keys()):
status.add_block(KEY_TO_CONTEXT[key], key, value)
else:
status.set_property(key, value)
@@ -303,7 +364,7 @@
if __name__ == '__main__':
args = parse_args()
- status = RaidStatus()
+ status = RaidStatus(get_physical=args.physical)
parse_megacli_status(status)
summary = status.get_status(get_all=args.all)
--
To view, visit https://gerrit.wikimedia.org/r/322249
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Idde1b95a2112de6badf029d911e160882ee54af2
Gerrit-PatchSet: 1
Gerrit-Project: operations/puppet
Gerrit-Branch: production
Gerrit-Owner: Volans <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits