Browse Source

Added is_jbod_capable method to raid resource

Some RAID controllers support JBOD (passthrough) mode, while others do not.
This method determines if the passed RAID controller supports JBOD mode.
Note: that the controller must have at least one disk in the non-RAID or ready
state, or this method will be unable to determine if the RAID controller
supports JBOD mode, and an exception will be thrown.

Co-Authored-By: Christopher Dearborn <Christopher.Dearborn@dell.com>
Change-Id: I62d8f92197faf6a6b4fe8a72da5c1a6a79d2af82
changes/64/578564/5
David Paterson 4 years ago
parent
commit
1d203354a2
  1. 14
      dracclient/client.py
  2. 60
      dracclient/resources/raid.py
  3. 115
      dracclient/tests/test_raid.py

14
dracclient/client.py

@ -677,6 +677,20 @@ class DRACClient(object):
return self.client.wait_until_idrac_is_ready(retries, retry_delay)
def is_jbod_capable(self, raid_controller_fqdd):
"""Find out if raid controller supports jbod
:param raid_controller_fqdd: The raid controller's fqdd
being being checked to see if it is jbod
capable.
:raises: DRACRequestFailed if unable to find any disks in the Ready
or non-RAID states
:raises: DRACOperationFailed on error reported back by the DRAC
and the exception message does not contain
NOT_SUPPORTED_MSG constant
"""
return self._raid_mgmt.is_jbod_capable(raid_controller_fqdd)
class WSManClient(wsman.Client):
"""Wrapper for wsman.Client that can wait until iDRAC is ready

60
dracclient/resources/raid.py

@ -151,6 +151,8 @@ class VirtualDisk(VirtualDiskTuple):
class RAIDManagement(object):
NOT_SUPPORTED_MSG = " operation is not supported on th"
def __init__(self, client):
"""Creates RAIDManagement object
@ -517,3 +519,61 @@ class RAIDManagement(object):
return utils.build_return_dict(doc, uris.DCIM_RAIDService,
include_commit_required=True,
is_commit_required_value=True)
def is_jbod_capable(self, raid_controller_fqdd):
"""Find out if raid controller supports jbod
:param raid_controller_fqdd: The raid controller's fqdd
being being checked to see if it is jbod
capable.
:raises: DRACRequestFailed if unable to find any disks in the Ready
or non-RAID states
:raises: DRACOperationFailed on error reported back by the DRAC
and the exception message does not contain
NOT_SUPPORTED_MSG constant
"""
is_jbod_capable = False
# Grab all the disks associated with the RAID controller
all_physical_disks = self.list_physical_disks()
physical_disks = [physical_disk for physical_disk in all_physical_disks
if physical_disk.controller == raid_controller_fqdd]
# If there is a disk in the Non-RAID state, then the controller is JBOD
# capable
ready_disk = None
for physical_disk in physical_disks:
if physical_disk.raid_status == 'non-RAID':
is_jbod_capable = True
break
elif not ready_disk and physical_disk.raid_status == 'ready':
ready_disk = physical_disk
if not is_jbod_capable:
if not ready_disk:
msg = "Unable to find a disk in the Ready state"
raise exceptions.DRACRequestFailed(msg)
# Try moving a disk in the Ready state to JBOD mode
try:
self.convert_physical_disks(
[ready_disk.id],
False)
is_jbod_capable = True
# Flip the disk back to the Ready state. This results in the
# pending value being reset to nothing, so it effectively
# undoes the last command and makes the check non-destructive
self.convert_physical_disks(
[ready_disk.id],
True)
except exceptions.DRACOperationFailed as ex:
# Fix for python 3, Exception.message no longer
# a valid attribute, str(ex) works for both 2.7
# and 3.x
if self.NOT_SUPPORTED_MSG in str(ex):
pass
else:
raise
return is_jbod_capable

115
dracclient/tests/test_raid.py

@ -34,6 +34,7 @@ class ClientRAIDManagementTestCase(base.BaseTest):
super(ClientRAIDManagementTestCase, self).setUp()
self.drac_client = dracclient.client.DRACClient(
**test_utils.FAKE_ENDPOINT)
self.raid_controller_fqdd = "RAID.Integrated.1-1"
@mock.patch.object(dracclient.client.WSManClient,
'wait_until_idrac_is_ready', spec_set=True,
@ -548,3 +549,117 @@ class ClientRAIDManagementTestCase(base.BaseTest):
mock.ANY, resource_uri=uris.DCIM_RAIDService,
cim_creation_class_name='DCIM_RAIDService',
cim_name='DCIM:RAIDService', target='controller')
@mock.patch.object(dracclient.client.WSManClient,
'wait_until_idrac_is_ready', spec_set=True,
autospec=True)
@mock.patch.object(dracclient.resources.raid.RAIDManagement,
'convert_physical_disks',
return_value={}, spec_set=True,
autospec=True)
def test_raid_controller_jbod_capable(self, mock_requests,
mock_wait_until_idrac_is_ready,
mock_convert_physical_disks):
mock_requests.post(
'https://1.2.3.4:443/wsman',
text=test_utils.RAIDEnumerations[uris.DCIM_PhysicalDiskView]['ok'])
is_jbod = self.drac_client.is_jbod_capable(self.raid_controller_fqdd)
self.assertTrue(is_jbod, msg="is_jbod is true")
@mock.patch.object(dracclient.client.WSManClient,
'wait_until_idrac_is_ready', spec_set=True,
autospec=True)
@mock.patch.object(dracclient.resources.raid.RAIDManagement,
'convert_physical_disks',
return_value={}, spec_set=True,
autospec=True)
def test_raid_controller_jbod_non_raid(self, mock_requests,
mock_wait_until_idrac_is_ready,
mock_convert_physical_disks):
pdv = test_utils.RAIDEnumerations[uris.DCIM_PhysicalDiskView]['ok']
# change to non-RAID value
pdv = pdv.replace("<n1:RaidStatus>1</n1:RaidStatus>",
"<n1:RaidStatus>8</n1:RaidStatus>")
mock_requests.post(
'https://1.2.3.4:443/wsman',
text=pdv)
is_jbod = self.drac_client.is_jbod_capable(self.raid_controller_fqdd)
self.assertTrue(is_jbod, msg="is_jbod is true")
@mock.patch.object(dracclient.client.WSManClient,
'wait_until_idrac_is_ready', spec_set=True,
autospec=True)
@mock.patch.object(dracclient.resources.raid.RAIDManagement,
'convert_physical_disks',
return_value={}, spec_set=True,
autospec=True)
def test_raid_controller_jbod_unknown(self, mock_requests,
mock_wait_until_idrac_is_ready,
mock_convert_physical_disks):
is_jbod = False
pdv = test_utils.RAIDEnumerations[uris.DCIM_PhysicalDiskView]['ok']
# change to non-RAID value
pdv = pdv.replace("<n1:RaidStatus>1</n1:RaidStatus>",
"<n1:RaidStatus>0</n1:RaidStatus>")
mock_requests.post(
'https://1.2.3.4:443/wsman',
text=pdv)
self.assertRaises(exceptions.DRACRequestFailed,
self.drac_client.is_jbod_capable,
self.raid_controller_fqdd)
self.assertFalse(is_jbod, msg="is_jbod is false")
@mock.patch.object(dracclient.client.WSManClient,
'wait_until_idrac_is_ready', spec_set=True,
autospec=True)
@mock.patch.object(dracclient.resources.raid.RAIDManagement,
'convert_physical_disks',
spec_set=True,
autospec=True)
def test_raid_controller_jbod_not_supported(self,
mock_requests,
mock_convert_physical_disks,
mock_wait_idrac_is_ready):
msg = " operation is not supported on th"
exc = exceptions.DRACOperationFailed(drac_messages=msg)
mock_convert_physical_disks.side_effect = exc
mock_requests.post(
'https://1.2.3.4:443/wsman',
text=test_utils.RAIDEnumerations[uris.DCIM_PhysicalDiskView]['ok'])
is_jbod = self.drac_client.is_jbod_capable(self.raid_controller_fqdd)
self.assertFalse(is_jbod, msg="is_jbod is false")
@mock.patch.object(dracclient.client.WSManClient,
'wait_until_idrac_is_ready', spec_set=True,
autospec=True)
@mock.patch.object(dracclient.resources.raid.RAIDManagement,
'convert_physical_disks',
spec_set=True,
autospec=True)
def test_raid_controller_jbod_ex_no_match(self,
mock_requests,
mock_convert_physical_disks,
mock_wait_until_idrac_is_ready):
mock_requests.post(
'https://1.2.3.4:443/wsman',
text=test_utils.RAIDEnumerations[uris.DCIM_PhysicalDiskView]['ok'])
msg = "NON_MATCHING_MESSAGE"
exc = exceptions.DRACOperationFailed(drac_messages=msg)
mock_convert_physical_disks.side_effect = exc
self.assertRaises(
exceptions.DRACOperationFailed,
self.drac_client.is_jbod_capable, self.raid_controller_fqdd)

Loading…
Cancel
Save