Fixed HP raid parser when disks are in JBOD

The function parsing the RAID logical volumes in the HP module did not
manage the case where disks were set in JBOD mode, thus having no RAID
array set.

This patch fixes this by checking if arrays are defined on pdisks before
parsing the logical disks.

Also added returncode read when executing the RAID related commands to
raise a more precise error.
This commit is contained in:
Christophe Simon 2022-03-11 15:55:07 +01:00
commit ad951b9288
3 changed files with 67 additions and 15 deletions

View file

@ -7,10 +7,26 @@ import re
REGEXP_CONTROLLER_HP = re.compile(r'Smart Array ([a-zA-Z0-9- ]+) in Slot ([0-9]+)') REGEXP_CONTROLLER_HP = re.compile(r'Smart Array ([a-zA-Z0-9- ]+) in Slot ([0-9]+)')
class HPRaidControllerError(Exception):
pass
def ssacli(command):
output = subprocess.getoutput('ssacli {}'.format(command) ) def ssacli(sub_command):
lines = output.split('\n') command = ["ssacli"]
command.extend(sub_command.split())
p = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT
)
p.wait()
stdout = p.stdout.read().decode("utf-8")
if p.returncode != 0:
mesg = "Failed to execute command '{}':\n{}".format(
" ".join(command), stdout
)
raise HPRaidControllerError(mesg)
lines = stdout.split('\n')
lines = list(filter(None, lines)) lines = list(filter(None, lines))
return lines return lines
@ -92,8 +108,10 @@ class HPRaidController(RaidController):
self.controller_name = controller_name self.controller_name = controller_name
self.data = data self.data = data
self.pdrives = self._get_physical_disks() self.pdrives = self._get_physical_disks()
self.ldrives = self._get_logical_drives() arrays = [d['Array'] for d in self.pdrives.values() if d.get('Array')]
self._get_virtual_drives_map() if arrays:
self.ldrives = self._get_logical_drives()
self._get_virtual_drives_map()
def get_product_name(self): def get_product_name(self):
return self.controller_name return self.controller_name
@ -135,6 +153,7 @@ class HPRaidController(RaidController):
'Type': 'SSD' if attrs.get('Interface Type') == 'Solid State SATA' 'Type': 'SSD' if attrs.get('Interface Type') == 'Solid State SATA'
else 'HDD', else 'HDD',
'_src': self.__class__.__name__, '_src': self.__class__.__name__,
'custom_fields': {'pd_identifier': name}
} }
return ret return ret
@ -164,8 +183,7 @@ class HPRaidController(RaidController):
" Ignoring.".format(name) " Ignoring.".format(name)
) )
continue continue
attrs['custom_fields'] = ld attrs['custom_fields'].update(ld)
attrs['custom_fields']['pd_identifier'] = name
def get_physical_disks(self): def get_physical_disks(self):
return list(self.pdrives.values()) return list(self.pdrives.values())

View file

@ -6,15 +6,32 @@ import logging
import re import re
class OmreportControllerError(Exception):
pass
def omreport(sub_command): def omreport(sub_command):
command = 'omreport {}'.format(sub_command) command = ["omreport"]
output = subprocess.getoutput(command) command.extend(sub_command.split())
p = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT
)
p.wait()
stdout = p.stdout.read().decode("utf-8")
if p.returncode != 0:
mesg = "Failed to execute command '{}':\n{}".format(
" ".join(command), stdout
)
raise OmreportControllerError(mesg)
res = {} res = {}
section_re = re.compile('^[A-Z]') section_re = re.compile('^[A-Z]')
current_section = None current_section = None
current_obj = None current_obj = None
for line in output.split('\n'): for line in stdout.split('\n'):
if ': ' in line: if ': ' in line:
attr, value = line.split(': ', 1) attr, value = line.split(': ', 1)
attr = attr.strip() attr = attr.strip()

View file

@ -8,10 +8,27 @@ import re
import os import os
class StorcliControllerError(Exception):
pass
def storecli(sub_command): def storecli(sub_command):
command = 'storcli {} J'.format(sub_command) command = ["storcli"]
output = subprocess.getoutput(command) command.extend(sub_command.split())
data = json.loads(output) command.append("J")
p = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT
)
p.wait()
stdout = p.stdout.read().decode("utf-8")
if p.returncode != 0:
mesg = "Failed to execute command '{}':\n{}".format(
" ".join(command), stdout
)
raise StorcliControllerError(mesg)
data = json.loads(stdout)
controllers = dict([ controllers = dict([
( (
c['Command Status']['Controller'], c['Command Status']['Controller'],
@ -22,7 +39,7 @@ def storecli(sub_command):
if not controllers: if not controllers:
logging.error( logging.error(
"Failed to execute command '{}'. " "Failed to execute command '{}'. "
"Ignoring data.".format(command) "Ignoring data.".format(" ".join(command))
) )
return {} return {}
return controllers return controllers