Add interface to convert disks to RAID mode
A new function, convert_physical_disks, converts disks to and from RAID mode. This function enables a Dell system at factory defaults to be initialised with a RAID configuration by python-dracclient. Change-Id: Ice40bfb47485056428a22c216990cf0a026c73d2
This commit is contained in:
parent
a696dcd94d
commit
3e9d66173b
@ -326,6 +326,25 @@ class DRACClient(object):
|
||||
"""
|
||||
return self._raid_mgmt.list_physical_disks()
|
||||
|
||||
def convert_physical_disks(self, raid_controller, physical_disks,
|
||||
raid_enable=True):
|
||||
"""Changes the operational mode of a physical disk.
|
||||
|
||||
Disks can be enabled or disabled for RAID mode.
|
||||
|
||||
:param raid_controller: the FQDD ID of the RAID controller
|
||||
:param physical_disks: list of FQDD ID strings of the physical disks
|
||||
to update
|
||||
:param raid_enable: boolean flag, set to True if the disk is to
|
||||
become part of the RAID. The same flag is applied to all
|
||||
listed disks
|
||||
:returns: a dictionary containing the commit_required key with a
|
||||
boolean value indicating whether a config job must be
|
||||
created for the values to be applied.
|
||||
"""
|
||||
return self._raid_mgmt.convert_physical_disks(
|
||||
physical_disks, raid_enable)
|
||||
|
||||
def create_virtual_disk(self, raid_controller, physical_disks, raid_level,
|
||||
size_mb, disk_name=None, span_length=None,
|
||||
span_depth=None):
|
||||
|
@ -234,6 +234,36 @@ class RAIDManagement(object):
|
||||
return utils.get_wsman_resource_attr(
|
||||
drac_disk, uris.DCIM_PhysicalDiskView, attr_name)
|
||||
|
||||
def convert_physical_disks(self, physical_disks, raid_enable):
|
||||
"""Converts a list of physical disks into or out of RAID mode.
|
||||
|
||||
Disks can be enabled or disabled for RAID mode.
|
||||
|
||||
:param physical_disks: list of FQDD ID strings of the physical disks
|
||||
to update
|
||||
:param raid_enable: boolean flag, set to True if the disk is to
|
||||
become part of the RAID. The same flag is applied to all
|
||||
listed disks
|
||||
:returns: a dictionary containing the commit_needed key with a boolean
|
||||
value indicating whether a config job must be created for the
|
||||
values to be applied.
|
||||
"""
|
||||
invocation = 'ConvertToRAID' if raid_enable else 'ConvertToNonRAID'
|
||||
|
||||
selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem',
|
||||
'CreationClassName': 'DCIM_RAIDService',
|
||||
'SystemName': 'DCIM:ComputerSystem',
|
||||
'Name': 'DCIM:RAIDService'}
|
||||
|
||||
properties = {'PDArray': physical_disks}
|
||||
|
||||
doc = self.client.invoke(uris.DCIM_RAIDService, invocation,
|
||||
selectors, properties,
|
||||
expected_return_value=utils.RET_SUCCESS)
|
||||
|
||||
return {'commit_required':
|
||||
utils.is_reboot_required(doc, uris.DCIM_RAIDService)}
|
||||
|
||||
def create_virtual_disk(self, raid_controller, physical_disks, raid_level,
|
||||
size_mb, disk_name=None, span_length=None,
|
||||
span_depth=None):
|
||||
|
@ -15,6 +15,7 @@ import re
|
||||
|
||||
import lxml.etree
|
||||
import mock
|
||||
import random
|
||||
import requests_mock
|
||||
|
||||
import dracclient.client
|
||||
@ -702,6 +703,162 @@ class ClientRAIDManagementTestCase(base.BaseTest):
|
||||
self.assertIn(expected_physical_disk,
|
||||
self.drac_client.list_physical_disks())
|
||||
|
||||
# Verify that various client convert_physical_disks calls to dracclient
|
||||
# result in a WSMan.invoke with appropriate parameters
|
||||
def _random_term(self):
|
||||
return "".join(random.sample('ABCDEFGHabcdefgh0123456',
|
||||
random.randint(4, 12)))
|
||||
|
||||
def _random_fqdd(self):
|
||||
result = self._random_term()
|
||||
for i in range(0, random.randint(6, 10)):
|
||||
result += random.sample('.:-', 1)[0] + self._random_term()
|
||||
return result
|
||||
|
||||
@mock.patch.object(dracclient.client.WSManClient, 'invoke',
|
||||
spec_set=True, autospec=True)
|
||||
def test_convert_physical_disks_1(self, mock_requests, mock_invoke):
|
||||
'''Convert a single disk to RAID mode'''
|
||||
device_fqdd = self._random_fqdd()
|
||||
expected_invocation = 'ConvertToRAID'
|
||||
expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem',
|
||||
'CreationClassName': 'DCIM_RAIDService',
|
||||
'SystemName': 'DCIM:ComputerSystem',
|
||||
'Name': 'DCIM:RAIDService'}
|
||||
expected_properties = {'PDArray': [device_fqdd]}
|
||||
|
||||
result = self.drac_client.convert_physical_disks(
|
||||
raid_controller='controller',
|
||||
physical_disks=[device_fqdd],
|
||||
raid_enable=True)
|
||||
|
||||
self.assertEqual({'commit_required': False}, result)
|
||||
mock_invoke.assert_called_once_with(
|
||||
mock.ANY, uris.DCIM_RAIDService, expected_invocation,
|
||||
expected_selectors, expected_properties,
|
||||
expected_return_value=utils.RET_SUCCESS)
|
||||
|
||||
@mock.patch.object(dracclient.client.WSManClient, 'invoke',
|
||||
spec_set=True, autospec=True)
|
||||
def test_convert_physical_disks_n(self, mock_requests, mock_invoke):
|
||||
'''Convert a number of disks to RAID mode'''
|
||||
device_list = []
|
||||
for i in range(0, random.randint(2, 10)):
|
||||
device_list += self._random_fqdd()
|
||||
|
||||
expected_invocation = 'ConvertToRAID'
|
||||
expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem',
|
||||
'CreationClassName': 'DCIM_RAIDService',
|
||||
'SystemName': 'DCIM:ComputerSystem',
|
||||
'Name': 'DCIM:RAIDService'}
|
||||
expected_properties = {'PDArray': device_list}
|
||||
|
||||
result = self.drac_client.convert_physical_disks(
|
||||
raid_controller='controller',
|
||||
physical_disks=device_list,
|
||||
raid_enable=True)
|
||||
|
||||
self.assertEqual({'commit_required': False}, result)
|
||||
mock_invoke.assert_called_once_with(
|
||||
mock.ANY, uris.DCIM_RAIDService, expected_invocation,
|
||||
expected_selectors, expected_properties,
|
||||
expected_return_value=utils.RET_SUCCESS)
|
||||
|
||||
@mock.patch.object(dracclient.client.WSManClient, 'invoke',
|
||||
spec_set=True, autospec=True)
|
||||
def test_convert_physical_disks_nonraid_1(self, mock_requests,
|
||||
mock_invoke):
|
||||
'''Convert a single disk to non-RAID mode'''
|
||||
device_fqdd = self._random_fqdd()
|
||||
expected_invocation = 'ConvertToNonRAID'
|
||||
expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem',
|
||||
'CreationClassName': 'DCIM_RAIDService',
|
||||
'SystemName': 'DCIM:ComputerSystem',
|
||||
'Name': 'DCIM:RAIDService'}
|
||||
expected_properties = {'PDArray': [device_fqdd]}
|
||||
|
||||
result = self.drac_client.convert_physical_disks(
|
||||
raid_controller='controller',
|
||||
physical_disks=[device_fqdd],
|
||||
raid_enable=False)
|
||||
|
||||
self.assertEqual({'commit_required': False}, result)
|
||||
mock_invoke.assert_called_once_with(
|
||||
mock.ANY, uris.DCIM_RAIDService, expected_invocation,
|
||||
expected_selectors, expected_properties,
|
||||
expected_return_value=utils.RET_SUCCESS)
|
||||
|
||||
@mock.patch.object(dracclient.client.WSManClient, 'invoke',
|
||||
spec_set=True, autospec=True)
|
||||
def test_convert_physical_disks_nonraid_n(self, mock_requests,
|
||||
mock_invoke):
|
||||
'''Convert a number of disks to non-RAID mode'''
|
||||
device_list = []
|
||||
for i in range(0, random.randint(2, 10)):
|
||||
device_list += self._random_fqdd()
|
||||
|
||||
expected_invocation = 'ConvertToNonRAID'
|
||||
expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem',
|
||||
'CreationClassName': 'DCIM_RAIDService',
|
||||
'SystemName': 'DCIM:ComputerSystem',
|
||||
'Name': 'DCIM:RAIDService'}
|
||||
expected_properties = {'PDArray': device_list}
|
||||
|
||||
result = self.drac_client.convert_physical_disks(
|
||||
raid_controller='controller',
|
||||
physical_disks=device_list,
|
||||
raid_enable=False)
|
||||
|
||||
self.assertEqual({'commit_required': False}, result)
|
||||
mock_invoke.assert_called_once_with(
|
||||
mock.ANY, uris.DCIM_RAIDService, expected_invocation,
|
||||
expected_selectors, expected_properties,
|
||||
expected_return_value=utils.RET_SUCCESS)
|
||||
|
||||
@mock.patch.object(dracclient.client.WSManClient, 'invoke',
|
||||
spec_set=True, autospec=True)
|
||||
def test_convert_physical_disks_ok(self, mock_requests, mock_invoke):
|
||||
'''Convert a number of disks to RAID mode and check the return value'''
|
||||
device_list = []
|
||||
for i in range(0, random.randint(2, 10)):
|
||||
device_list += self._random_fqdd()
|
||||
|
||||
expected_invocation = 'ConvertToRAID'
|
||||
expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem',
|
||||
'CreationClassName': 'DCIM_RAIDService',
|
||||
'SystemName': 'DCIM:ComputerSystem',
|
||||
'Name': 'DCIM:RAIDService'}
|
||||
expected_properties = {'PDArray': device_list}
|
||||
|
||||
mock_invoke.return_value = lxml.etree.fromstring(
|
||||
test_utils.RAIDInvocations[uris.DCIM_RAIDService][
|
||||
expected_invocation]['ok'])
|
||||
|
||||
result = self.drac_client.convert_physical_disks(
|
||||
raid_controller='controller',
|
||||
physical_disks=device_list,
|
||||
raid_enable=True)
|
||||
|
||||
self.assertEqual({'commit_required': True}, result)
|
||||
mock_invoke.assert_called_once_with(
|
||||
mock.ANY, uris.DCIM_RAIDService, expected_invocation,
|
||||
expected_selectors, expected_properties,
|
||||
expected_return_value=utils.RET_SUCCESS)
|
||||
|
||||
def test_convert_physical_disks_fail(self, mock_requests):
|
||||
mock_requests.post(
|
||||
'https://1.2.3.4:443/wsman',
|
||||
text=test_utils.RAIDInvocations[
|
||||
uris.DCIM_RAIDService]['ConvertToRAID']['error'])
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.DRACOperationFailed,
|
||||
self.drac_client.convert_physical_disks,
|
||||
raid_controller='controller',
|
||||
physical_disks=['Disk0:Enclosure-1:RAID-1',
|
||||
'Disk1:Enclosure-1:RAID-1'],
|
||||
raid_enable=True)
|
||||
|
||||
@mock.patch.object(dracclient.client.WSManClient, 'invoke',
|
||||
spec_set=True, autospec=True)
|
||||
def test_create_virtual_disk(self, mock_requests, mock_invoke):
|
||||
|
@ -164,6 +164,12 @@ RAIDInvocations = {
|
||||
'raid_service-invoke-delete_virtual_disk-ok'),
|
||||
'error': load_wsman_xml(
|
||||
'raid_service-invoke-delete_virtual_disk-error'),
|
||||
},
|
||||
'ConvertToRAID': {
|
||||
'ok': load_wsman_xml(
|
||||
'raid_service-invoke-convert_physical_disks-ok'),
|
||||
'error': load_wsman_xml(
|
||||
'raid_service-invoke-convert_physical_disks-error'),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:n1="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_RAIDService">
|
||||
<s:Header>
|
||||
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
|
||||
<wsa:Action>http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_RAIDService/ConvertToRAIDResponse</wsa:Action>
|
||||
<wsa:RelatesTo>uuid:6364e38d-4e3c-4769-8c67-ff4332ea603a</wsa:RelatesTo>
|
||||
<wsa:MessageID>uuid:ad08919a-34b2-14b2-a4b0-ea19c46a0064</wsa:MessageID>
|
||||
</s:Header>
|
||||
<s:Body>
|
||||
<n1:ConvertToRAID_OUTPUT>
|
||||
<n1:Message>Invalid parameter value</n1:Message>
|
||||
<n1:MessageArguments>NULL</n1:MessageArguments>
|
||||
<n1:MessageID>STOR004</n1:MessageID>
|
||||
<n1:ReturnValue>2</n1:ReturnValue>
|
||||
</n1:ConvertToRAID_OUTPUT>
|
||||
</s:Body>
|
||||
</s:Envelope>
|
@ -0,0 +1,14 @@
|
||||
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:n1="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_RAIDService">
|
||||
<s:Header>
|
||||
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
|
||||
<wsa:Action>http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_RAIDService/ConvertToRAIDResponse</wsa:Action>
|
||||
<wsa:RelatesTo>uuid:c6c4bcf6-c340-4f0b-9aef-3c7be94f0d61</wsa:RelatesTo>
|
||||
<wsa:MessageID>uuid:3223ac5b-3439-1439-9855-ea19c46a0064</wsa:MessageID>
|
||||
</s:Header>
|
||||
<s:Body>
|
||||
<n1:ConvertToRAID_OUTPUT>
|
||||
<n1:RebootRequired>YES</n1:RebootRequired>
|
||||
<n1:ReturnValue>0</n1:ReturnValue>
|
||||
</n1:ConvertToRAID_OUTPUT>
|
||||
</s:Body>
|
||||
</s:Envelope>
|
Loading…
x
Reference in New Issue
Block a user