IPA: Update proliant hardware manager
This commit updates proliant hardware manager as per the latest Ironic: * Every clean step and get_clean_steps() must accept the arguments node and ports which are dictionaries. * Removes erase clean step using shred because it is already supported in IPA. * Register create_configuration and delete_configuration as clean steps. * Make delete_configuration() return the current raid configuration on the system. Change-Id: Ia8f0139e9b86abdee7566e352788b1fa53ad09d9
This commit is contained in:
parent
19be723a66
commit
6290ce9938
@ -163,13 +163,18 @@ def create_configuration(raid_config):
|
|||||||
|
|
||||||
|
|
||||||
def delete_configuration():
|
def delete_configuration():
|
||||||
"""Delete a RAID configuration on this server."""
|
"""Delete a RAID configuration on this server.
|
||||||
|
|
||||||
|
:returns: the current RAID configuration after deleting all
|
||||||
|
the logical disks.
|
||||||
|
"""
|
||||||
server = objects.Server()
|
server = objects.Server()
|
||||||
for controller in server.controllers:
|
for controller in server.controllers:
|
||||||
# Trigger delete only if there is some RAID array, otherwise
|
# Trigger delete only if there is some RAID array, otherwise
|
||||||
# hpssacli will fail saying "no logical drives found."
|
# hpssacli will fail saying "no logical drives found."
|
||||||
if controller.raid_arrays:
|
if controller.raid_arrays:
|
||||||
controller.delete_all_logical_drives()
|
controller.delete_all_logical_drives()
|
||||||
|
return get_configuration()
|
||||||
|
|
||||||
|
|
||||||
def get_configuration():
|
def get_configuration():
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from ironic_python_agent import hardware
|
from ironic_python_agent import hardware
|
||||||
from oslo_concurrency import processutils
|
|
||||||
|
|
||||||
from proliantutils.hpssa import manager as hpssa_manager
|
from proliantutils.hpssa import manager as hpssa_manager
|
||||||
|
|
||||||
@ -22,25 +21,62 @@ class ProliantHardwareManager(hardware.GenericHardwareManager):
|
|||||||
|
|
||||||
HARDWARE_MANAGER_VERSION = "3"
|
HARDWARE_MANAGER_VERSION = "3"
|
||||||
|
|
||||||
def get_clean_steps(self):
|
def get_clean_steps(self, node, ports):
|
||||||
pass
|
"""Return the clean steps supported by this hardware manager.
|
||||||
|
|
||||||
|
This method returns the clean steps that are supported by
|
||||||
|
proliant hardware manager. This method is invoked on every
|
||||||
|
hardware manager by Ironic Python Agent to give this information
|
||||||
|
back to Ironic.
|
||||||
|
|
||||||
|
:param node: A dictionary of the node object
|
||||||
|
:param ports: A list of dictionaries containing information of ports
|
||||||
|
for the node
|
||||||
|
:returns: A list of dictionaries, each item containing the step name,
|
||||||
|
interface and priority for the clean step.
|
||||||
|
"""
|
||||||
|
return [{'step': 'create_configuration',
|
||||||
|
'interface': 'raid',
|
||||||
|
'priority': 0},
|
||||||
|
{'step': 'delete_configuration',
|
||||||
|
'interface': 'raid',
|
||||||
|
'priority': 0}]
|
||||||
|
|
||||||
def evaluate_hardware_support(cls):
|
def evaluate_hardware_support(cls):
|
||||||
return hardware.HardwareSupport.SERVICE_PROVIDER
|
return hardware.HardwareSupport.SERVICE_PROVIDER
|
||||||
|
|
||||||
def erase_block_device(self, block_device):
|
def create_configuration(self, node, ports):
|
||||||
npass = 3
|
"""Create RAID configuration on the bare metal.
|
||||||
cmd = ('shred', '--force', '--zero', '--verbose',
|
|
||||||
'--iterations', npass, block_device.name)
|
|
||||||
processutils.execute(*cmd)
|
|
||||||
|
|
||||||
def erase_devices(self):
|
This method creates the desired RAID configuration as read from
|
||||||
block_devices = self.list_block_devices()
|
node['target_raid_config'].
|
||||||
for block_device in block_devices:
|
|
||||||
self.erase_block_device(block_device)
|
|
||||||
|
|
||||||
def create_raid_configuration(self, raid_config):
|
:param node: A dictionary of the node object
|
||||||
return hpssa_manager.create_configuration(raid_config=raid_config)
|
:param ports: A list of dictionaries containing information of ports
|
||||||
|
for the node
|
||||||
|
:returns: The current RAID configuration of the below format.
|
||||||
|
raid_config = {
|
||||||
|
'logical_disks': [{
|
||||||
|
'size_gb': 100,
|
||||||
|
'raid_level': 1,
|
||||||
|
'physical_disks': [
|
||||||
|
'5I:0:1',
|
||||||
|
'5I:0:2'],
|
||||||
|
'controller': 'Smart array controller'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
target_raid_config = node.get('target_raid_config', {}).copy()
|
||||||
|
return hpssa_manager.create_configuration(
|
||||||
|
raid_config=target_raid_config)
|
||||||
|
|
||||||
def delete_raid_configuration(self):
|
def delete_configuration(self, node, ports):
|
||||||
hpssa_manager.delete_configuration()
|
"""Deletes RAID configuration on the bare metal.
|
||||||
|
|
||||||
|
This method deletes all the RAID disks on the bare metal.
|
||||||
|
:param node: A dictionary of the node object
|
||||||
|
:param ports: A list of dictionaries containing information of ports
|
||||||
|
for the node
|
||||||
|
"""
|
||||||
|
return hpssa_manager.delete_configuration()
|
||||||
|
@ -201,27 +201,36 @@ class ManagerTestCases(testtools.TestCase):
|
|||||||
'array', 'A', 'create', 'type=logicaldrive', 'raid=1',
|
'array', 'A', 'create', 'type=logicaldrive', 'raid=1',
|
||||||
'size=51200')
|
'size=51200')
|
||||||
|
|
||||||
|
@mock.patch.object(manager, 'get_configuration')
|
||||||
@mock.patch.object(objects.Controller, 'execute_cmd')
|
@mock.patch.object(objects.Controller, 'execute_cmd')
|
||||||
def test_delete_configuration(self, controller_exec_cmd_mock,
|
def test_delete_configuration(self, controller_exec_cmd_mock,
|
||||||
|
get_configuration_mock,
|
||||||
get_all_details_mock):
|
get_all_details_mock):
|
||||||
|
|
||||||
get_all_details_mock.return_value = raid_constants.HPSSA_ONE_DRIVE
|
get_all_details_mock.return_value = raid_constants.HPSSA_ONE_DRIVE
|
||||||
|
get_configuration_mock.return_value = 'foo'
|
||||||
|
|
||||||
manager.delete_configuration()
|
ret = manager.delete_configuration()
|
||||||
|
|
||||||
controller_exec_cmd_mock.assert_called_with("logicaldrive",
|
controller_exec_cmd_mock.assert_called_with(
|
||||||
"all",
|
"logicaldrive", "all", "delete", "forced")
|
||||||
"delete",
|
get_configuration_mock.assert_called_once_with()
|
||||||
"forced")
|
self.assertEqual('foo', ret)
|
||||||
|
|
||||||
|
@mock.patch.object(manager, 'get_configuration')
|
||||||
@mock.patch.object(objects.Controller, 'execute_cmd')
|
@mock.patch.object(objects.Controller, 'execute_cmd')
|
||||||
def test_delete_configuration_no_arrays(
|
def test_delete_configuration_no_arrays(
|
||||||
self, controller_exec_cmd_mock, get_all_details_mock):
|
self, controller_exec_cmd_mock,
|
||||||
|
get_configuration_mock, get_all_details_mock):
|
||||||
|
|
||||||
get_all_details_mock.return_value = raid_constants.HPSSA_NO_DRIVES
|
get_all_details_mock.return_value = raid_constants.HPSSA_NO_DRIVES
|
||||||
|
get_configuration_mock.return_value = 'foo'
|
||||||
|
|
||||||
|
ret = manager.delete_configuration()
|
||||||
|
|
||||||
manager.delete_configuration()
|
|
||||||
self.assertFalse(controller_exec_cmd_mock.called)
|
self.assertFalse(controller_exec_cmd_mock.called)
|
||||||
|
get_configuration_mock.assert_called_once_with()
|
||||||
|
self.assertEqual('foo', ret)
|
||||||
|
|
||||||
def test_get_configuration(self, get_all_details_mock):
|
def test_get_configuration(self, get_all_details_mock):
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
from oslo_concurrency import processutils
|
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
from proliantutils.hpssa import manager as hpssa_manager
|
from proliantutils.hpssa import manager as hpssa_manager
|
||||||
@ -26,35 +25,28 @@ class ProliantHardwareManagerTestCase(testtools.TestCase):
|
|||||||
self.hardware_manager = hardware_manager.ProliantHardwareManager()
|
self.hardware_manager = hardware_manager.ProliantHardwareManager()
|
||||||
super(ProliantHardwareManagerTestCase, self).setUp()
|
super(ProliantHardwareManagerTestCase, self).setUp()
|
||||||
|
|
||||||
@mock.patch.object(processutils, 'execute')
|
def test_get_clean_steps(self):
|
||||||
def test_erase_block_device(self, processutils_mock):
|
self.assertEqual(
|
||||||
device = mock.MagicMock()
|
[{'step': 'create_configuration',
|
||||||
p = mock.PropertyMock(return_value='/dev/sda')
|
'interface': 'raid',
|
||||||
type(device).name = p
|
'priority': 0},
|
||||||
cmd_expected = ('shred', '--force', '--zero', '--verbose',
|
{'step': 'delete_configuration',
|
||||||
'--iterations', 3, '/dev/sda')
|
'interface': 'raid',
|
||||||
self.hardware_manager.erase_block_device(device)
|
'priority': 0}],
|
||||||
processutils_mock.assert_called_once_with(*cmd_expected)
|
self.hardware_manager.get_clean_steps("", ""))
|
||||||
|
|
||||||
@mock.patch.object(hardware_manager.ProliantHardwareManager,
|
|
||||||
'erase_block_device')
|
|
||||||
def test_erase_devices(self, erase_block_device_mock):
|
|
||||||
disks = ['/dev/sda', '/dev/sdb']
|
|
||||||
self.hardware_manager.list_block_devices.return_value = disks
|
|
||||||
self.hardware_manager.erase_devices()
|
|
||||||
self.hardware_manager.list_block_devices.assert_called_once_with()
|
|
||||||
erase_block_device_mock.assert_any_call('/dev/sda')
|
|
||||||
erase_block_device_mock.assert_any_call('/dev/sdb')
|
|
||||||
|
|
||||||
@mock.patch.object(hpssa_manager, 'create_configuration')
|
@mock.patch.object(hpssa_manager, 'create_configuration')
|
||||||
def test_create_raid_configuration(self, create_mock):
|
def test_create_configuration(self, create_mock):
|
||||||
create_mock.return_value = 'current-config'
|
create_mock.return_value = 'current-config'
|
||||||
manager = self.hardware_manager
|
manager = self.hardware_manager
|
||||||
ret = manager.create_raid_configuration(raid_config='target')
|
node = {'target_raid_config': {'foo': 'bar'}}
|
||||||
create_mock.assert_called_once_with(raid_config='target')
|
ret = manager.create_configuration(node, [])
|
||||||
|
create_mock.assert_called_once_with(raid_config={'foo': 'bar'})
|
||||||
self.assertEqual('current-config', ret)
|
self.assertEqual('current-config', ret)
|
||||||
|
|
||||||
@mock.patch.object(hpssa_manager, 'delete_configuration')
|
@mock.patch.object(hpssa_manager, 'delete_configuration')
|
||||||
def test_delete_raid_configuration(self, delete_mock):
|
def test_delete_configuration(self, delete_mock):
|
||||||
self.hardware_manager.delete_raid_configuration()
|
delete_mock.return_value = 'current-config'
|
||||||
|
ret = self.hardware_manager.delete_configuration("", "")
|
||||||
delete_mock.assert_called_once_with()
|
delete_mock.assert_called_once_with()
|
||||||
|
self.assertEqual('current-config', ret)
|
||||||
|
Loading…
Reference in New Issue
Block a user