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:
Ramakrishnan G 2015-07-05 23:06:48 -07:00
parent 19be723a66
commit 6290ce9938
4 changed files with 91 additions and 49 deletions

View File

@ -163,13 +163,18 @@ def create_configuration(raid_config):
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()
for controller in server.controllers:
# Trigger delete only if there is some RAID array, otherwise
# hpssacli will fail saying "no logical drives found."
if controller.raid_arrays:
controller.delete_all_logical_drives()
return get_configuration()
def get_configuration():

View File

@ -13,7 +13,6 @@
# under the License.
from ironic_python_agent import hardware
from oslo_concurrency import processutils
from proliantutils.hpssa import manager as hpssa_manager
@ -22,25 +21,62 @@ class ProliantHardwareManager(hardware.GenericHardwareManager):
HARDWARE_MANAGER_VERSION = "3"
def get_clean_steps(self):
pass
def get_clean_steps(self, node, ports):
"""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):
return hardware.HardwareSupport.SERVICE_PROVIDER
def erase_block_device(self, block_device):
npass = 3
cmd = ('shred', '--force', '--zero', '--verbose',
'--iterations', npass, block_device.name)
processutils.execute(*cmd)
def create_configuration(self, node, ports):
"""Create RAID configuration on the bare metal.
def erase_devices(self):
block_devices = self.list_block_devices()
for block_device in block_devices:
self.erase_block_device(block_device)
This method creates the desired RAID configuration as read from
node['target_raid_config'].
def create_raid_configuration(self, raid_config):
return hpssa_manager.create_configuration(raid_config=raid_config)
:param node: A dictionary of the node object
: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):
hpssa_manager.delete_configuration()
def delete_configuration(self, node, ports):
"""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()

View File

@ -201,27 +201,36 @@ class ManagerTestCases(testtools.TestCase):
'array', 'A', 'create', 'type=logicaldrive', 'raid=1',
'size=51200')
@mock.patch.object(manager, 'get_configuration')
@mock.patch.object(objects.Controller, 'execute_cmd')
def test_delete_configuration(self, controller_exec_cmd_mock,
get_configuration_mock,
get_all_details_mock):
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",
"all",
"delete",
"forced")
controller_exec_cmd_mock.assert_called_with(
"logicaldrive", "all", "delete", "forced")
get_configuration_mock.assert_called_once_with()
self.assertEqual('foo', ret)
@mock.patch.object(manager, 'get_configuration')
@mock.patch.object(objects.Controller, 'execute_cmd')
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_configuration_mock.return_value = 'foo'
ret = manager.delete_configuration()
manager.delete_configuration()
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):

View File

@ -13,7 +13,6 @@
# under the License.
import mock
from oslo_concurrency import processutils
import testtools
from proliantutils.hpssa import manager as hpssa_manager
@ -26,35 +25,28 @@ class ProliantHardwareManagerTestCase(testtools.TestCase):
self.hardware_manager = hardware_manager.ProliantHardwareManager()
super(ProliantHardwareManagerTestCase, self).setUp()
@mock.patch.object(processutils, 'execute')
def test_erase_block_device(self, processutils_mock):
device = mock.MagicMock()
p = mock.PropertyMock(return_value='/dev/sda')
type(device).name = p
cmd_expected = ('shred', '--force', '--zero', '--verbose',
'--iterations', 3, '/dev/sda')
self.hardware_manager.erase_block_device(device)
processutils_mock.assert_called_once_with(*cmd_expected)
@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')
def test_get_clean_steps(self):
self.assertEqual(
[{'step': 'create_configuration',
'interface': 'raid',
'priority': 0},
{'step': 'delete_configuration',
'interface': 'raid',
'priority': 0}],
self.hardware_manager.get_clean_steps("", ""))
@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'
manager = self.hardware_manager
ret = manager.create_raid_configuration(raid_config='target')
create_mock.assert_called_once_with(raid_config='target')
node = {'target_raid_config': {'foo': 'bar'}}
ret = manager.create_configuration(node, [])
create_mock.assert_called_once_with(raid_config={'foo': 'bar'})
self.assertEqual('current-config', ret)
@mock.patch.object(hpssa_manager, 'delete_configuration')
def test_delete_raid_configuration(self, delete_mock):
self.hardware_manager.delete_raid_configuration()
def test_delete_configuration(self, delete_mock):
delete_mock.return_value = 'current-config'
ret = self.hardware_manager.delete_configuration("", "")
delete_mock.assert_called_once_with()
self.assertEqual('current-config', ret)