Merge "Add constituent physical disks to RAID virtual disk object"

This commit is contained in:
Jenkins 2017-01-16 18:00:13 +00:00 committed by Gerrit Code Review
commit 5b987d4495
5 changed files with 141 additions and 8 deletions

View File

@ -113,7 +113,7 @@ VirtualDiskTuple = collections.namedtuple(
'VirtualDisk', 'VirtualDisk',
['id', 'name', 'description', 'controller', 'raid_level', 'size_mb', ['id', 'name', 'description', 'controller', 'raid_level', 'size_mb',
'status', 'raid_status', 'span_depth', 'span_length', 'status', 'raid_status', 'span_depth', 'span_length',
'pending_operations']) 'pending_operations', 'physical_disks'])
class VirtualDisk(VirtualDiskTuple): class VirtualDisk(VirtualDiskTuple):
@ -239,13 +239,19 @@ class RAIDManagement(object):
span_length=int(self._get_virtual_disk_attr(drac_disk, span_length=int(self._get_virtual_disk_attr(drac_disk,
'SpanLength')), 'SpanLength')),
pending_operations=( pending_operations=(
VIRTUAL_DISK_PENDING_OPERATIONS[drac_pending_operations])) VIRTUAL_DISK_PENDING_OPERATIONS[drac_pending_operations]),
physical_disks=self._get_virtual_disk_attrs(drac_disk,
'PhysicalDiskIDs'))
def _get_virtual_disk_attr(self, drac_disk, attr_name, nullable=False): def _get_virtual_disk_attr(self, drac_disk, attr_name, nullable=False):
return utils.get_wsman_resource_attr( return utils.get_wsman_resource_attr(
drac_disk, uris.DCIM_VirtualDiskView, attr_name, drac_disk, uris.DCIM_VirtualDiskView, attr_name,
nullable=nullable) nullable=nullable)
def _get_virtual_disk_attrs(self, drac_disk, attr_name):
return utils.get_all_wsman_resource_attrs(
drac_disk, uris.DCIM_VirtualDiskView, attr_name, nullable=False)
def list_physical_disks(self): def list_physical_disks(self):
"""Returns the list of physical disks """Returns the list of physical disks

View File

@ -62,7 +62,11 @@ class ClientRAIDManagementTestCase(base.BaseTest):
raid_status='online', raid_status='online',
span_depth=1, span_depth=1,
span_length=2, span_length=2,
pending_operations=None) pending_operations=None,
physical_disks=[
'Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1',
'Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1'
])
mock_requests.post( mock_requests.post(
'https://1.2.3.4:443/wsman', 'https://1.2.3.4:443/wsman',
@ -452,7 +456,7 @@ class ClientRAIDManagementTestCase(base.BaseTest):
@mock.patch.object(dracclient.resources.job.JobManagement, @mock.patch.object(dracclient.resources.job.JobManagement,
'delete_pending_config', spec_set=True, autospec=True) 'delete_pending_config', spec_set=True, autospec=True)
def test_abandon_pending_bios_changes(self, mock_requests, def test_abandon_pending_raid_changes(self, mock_requests,
mock_delete_pending_config): mock_delete_pending_config):
self.drac_client.abandon_pending_raid_changes('controller') self.drac_client.abandon_pending_raid_changes('controller')

View File

@ -27,6 +27,28 @@ class UtilsTestCase(base.BaseTest):
def setUp(self): def setUp(self):
super(UtilsTestCase, self).setUp() super(UtilsTestCase, self).setUp()
def test__is_attr_non_nil_True(self):
doc = etree.fromstring(
test_utils.RAIDEnumerations[
uris.DCIM_ControllerView]['ok'])
controllers = utils.find_xml(doc, 'DCIM_ControllerView',
uris.DCIM_ControllerView, find_all=True)
version = utils.find_xml(controllers[0], 'Bus',
uris.DCIM_ControllerView)
self.assertTrue(utils._is_attr_non_nil(version))
def test__is_attr_non_nil_False(self):
doc = etree.fromstring(
test_utils.RAIDEnumerations[
uris.DCIM_ControllerView]['ok'])
controllers = utils.find_xml(doc, 'DCIM_ControllerView',
uris.DCIM_ControllerView, find_all=True)
version = utils.find_xml(controllers[0], 'DriverVersion',
uris.DCIM_ControllerView)
self.assertFalse(utils._is_attr_non_nil(version))
def test_get_wsman_resource_attr(self): def test_get_wsman_resource_attr(self):
doc = etree.fromstring( doc = etree.fromstring(
test_utils.InventoryEnumerations[uris.DCIM_CPUView]['ok']) test_utils.InventoryEnumerations[uris.DCIM_CPUView]['ok'])
@ -79,3 +101,68 @@ class UtilsTestCase(base.BaseTest):
exceptions.DRACEmptyResponseField, re.escape(expected_message), exceptions.DRACEmptyResponseField, re.escape(expected_message),
utils.get_wsman_resource_attr, cpus[0], uris.DCIM_CPUView, utils.get_wsman_resource_attr, cpus[0], uris.DCIM_CPUView,
'HyperThreadingEnabled', allow_missing=False) 'HyperThreadingEnabled', allow_missing=False)
def test_get_wsman_resource_attr_missing_text_allowed(self):
doc = etree.fromstring(
test_utils.RAIDEnumerations[
uris.DCIM_ControllerView]['ok'])
controllers = utils.find_xml(doc, 'DCIM_ControllerView',
uris.DCIM_ControllerView, find_all=True)
result = utils.get_wsman_resource_attr(
controllers[0], uris.DCIM_ControllerView, 'DriverVersion',
allow_missing=False, nullable=True)
self.assertIsNone(result)
def test_get_all_wsman_resource_attrs(self):
doc = etree.fromstring(
test_utils.RAIDEnumerations[uris.DCIM_VirtualDiskView]['ok'])
vdisks = utils.find_xml(doc, 'DCIM_VirtualDiskView',
uris.DCIM_VirtualDiskView, find_all=True)
vals = utils.get_all_wsman_resource_attrs(
vdisks[0], uris.DCIM_VirtualDiskView, 'PhysicalDiskIDs')
expected_pdisks = [
'Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1',
'Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1'
]
self.assertListEqual(expected_pdisks, vals)
def test_get_all_wsman_resource_attrs_missing_attr_allowed(self):
doc = etree.fromstring(
test_utils.InventoryEnumerations[
uris.DCIM_CPUView]['missing_flags'])
cpus = utils.find_xml(doc, 'DCIM_CPUView', uris.DCIM_CPUView,
find_all=True)
vals = utils.get_all_wsman_resource_attrs(
cpus[0], uris.DCIM_CPUView, 'HyperThreadingEnabled')
self.assertListEqual([], vals)
def test_get_all_wsman_resource_attrs_missing_text(self):
expected_message = ("Attribute 'HyperThreadingEnabled' is not nullable"
", but no value received")
doc = etree.fromstring(
test_utils.InventoryEnumerations[
uris.DCIM_CPUView]['empty_flag'])
cpus = utils.find_xml(doc, 'DCIM_CPUView', uris.DCIM_CPUView,
find_all=True)
self.assertRaisesRegexp(
exceptions.DRACEmptyResponseField, re.escape(expected_message),
utils.get_all_wsman_resource_attrs, cpus[0], uris.DCIM_CPUView,
'HyperThreadingEnabled')
def test_get_all_wsman_resource_attrs_missing_text_allowed(self):
doc = etree.fromstring(
test_utils.RAIDEnumerations[
uris.DCIM_ControllerView]['ok'])
controllers = utils.find_xml(doc, 'DCIM_ControllerView',
uris.DCIM_ControllerView, find_all=True)
result = utils.get_all_wsman_resource_attrs(
controllers[0], uris.DCIM_ControllerView, 'DriverVersion',
nullable=True)
self.assertEqual(result, [])

View File

@ -30,7 +30,8 @@
<n1:OperationName>Background Intialization</n1:OperationName> <n1:OperationName>Background Intialization</n1:OperationName>
<n1:OperationPercentComplete>8</n1:OperationPercentComplete> <n1:OperationPercentComplete>8</n1:OperationPercentComplete>
<n1:PendingOperations>0</n1:PendingOperations> <n1:PendingOperations>0</n1:PendingOperations>
<n1:PhysicalDiskIDs xsi:nil="true"/> <n1:PhysicalDiskIDs>Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1</n1:PhysicalDiskIDs>
<n1:PhysicalDiskIDs>Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1</n1:PhysicalDiskIDs>
<n1:PrimaryStatus>1</n1:PrimaryStatus> <n1:PrimaryStatus>1</n1:PrimaryStatus>
<n1:RAIDStatus>2</n1:RAIDStatus> <n1:RAIDStatus>2</n1:RAIDStatus>
<n1:RAIDTypes>4</n1:RAIDTypes> <n1:RAIDTypes>4</n1:RAIDTypes>
@ -51,4 +52,4 @@
<wsman:EndOfSequence/> <wsman:EndOfSequence/>
</wsen:EnumerateResponse> </wsen:EnumerateResponse>
</s:Body> </s:Body>
</s:Envelope> </s:Envelope>

View File

@ -46,6 +46,15 @@ def find_xml(doc, item, namespace, find_all=False):
return doc.find(query) return doc.find(query)
def _is_attr_non_nil(elem):
"""Return whether an element is non-nil.
:param elem: the element object.
:returns: whether the element is nil.
"""
return elem.attrib.get('{%s}nil' % NS_XMLSchema_Instance) != 'true'
def get_wsman_resource_attr(doc, resource_uri, attr_name, nullable=False, def get_wsman_resource_attr(doc, resource_uri, attr_name, nullable=False,
allow_missing=False): allow_missing=False):
"""Find an attribute of a resource in an ElementTree object. """Find an attribute of a resource in an ElementTree object.
@ -78,11 +87,37 @@ def get_wsman_resource_attr(doc, resource_uri, attr_name, nullable=False,
raise exceptions.DRACEmptyResponseField(attr=attr_name) raise exceptions.DRACEmptyResponseField(attr=attr_name)
return item.text.strip() return item.text.strip()
else: else:
nil_attr = item.attrib.get('{%s}nil' % NS_XMLSchema_Instance) if _is_attr_non_nil(item):
if nil_attr != 'true':
return item.text.strip() return item.text.strip()
def get_all_wsman_resource_attrs(doc, resource_uri, attr_name, nullable=False):
"""Find all instances of an attribute of a resource in an ElementTree.
:param doc: the element tree object.
:param resource_uri: the resource URI of the namespace.
:param attr_name: the name of the attribute.
:param nullable: enables checking if any of the elements contain an
XMLSchema-instance namespaced nil attribute that has a
value of True. In this case, these elements will not be
returned.
:raises: DRACEmptyResponseField if any of the attributes in the XML doc
have no text and nullable is False.
:returns: a list containing the value of each of the instances of the
attribute.
"""
items = find_xml(doc, attr_name, resource_uri, find_all=True)
if not nullable:
for item in items:
if item.text is None:
raise exceptions.DRACEmptyResponseField(attr=attr_name)
return [item.text.strip() for item in items]
else:
return [item.text.strip() for item in items if _is_attr_non_nil(item)]
def is_reboot_required(doc, resource_uri): def is_reboot_required(doc, resource_uri):
"""Check the response document if reboot is requested. """Check the response document if reboot is requested.