Add Sanitize disk erase support using SSA
This commit adds the implementation to perfrom sanitize disk erase on the disks attached to the Smart storage controller using ssacli. Closes-bug: #1648807 Change-Id: I2a015345a31113f9f9a95b7dd722eb9b3a6bda43
This commit is contained in:
@@ -22,6 +22,7 @@ from proliantutils import exception
|
||||
from proliantutils.hpssa import constants
|
||||
from proliantutils.hpssa import disk_allocator
|
||||
from proliantutils.hpssa import objects
|
||||
from proliantutils.ilo import common
|
||||
|
||||
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
RAID_CONFIG_SCHEMA = os.path.join(CURRENT_DIR, "raid_config_schema.json")
|
||||
@@ -74,27 +75,32 @@ def validate(raid_config):
|
||||
raise exception.InvalidInputError(msg)
|
||||
|
||||
|
||||
def _filter_raid_mode_controllers(server):
|
||||
"""Filters out the hpssa controllers in raid mode.
|
||||
def _select_controllers_by(server, select_condition, msg):
|
||||
"""Filters out the hpssa controllers based on the condition.
|
||||
|
||||
This method updates the server with only the controller which is in raid
|
||||
mode. The controller which are in HBA mode are removed from the list.
|
||||
This method updates the server with only the controller which satisfies
|
||||
the condition. The controllers which doesn't satisfies the selection
|
||||
condition will be removed from the list.
|
||||
|
||||
:param server: The object containing all the supported hpssa controllers
|
||||
details.
|
||||
:param select_condition: A lambda function to select the controllers based
|
||||
on requirement.
|
||||
:param msg: A String which describes the controller selection.
|
||||
:raises exception.HPSSAOperationError, if all the controller are in HBA
|
||||
mode.
|
||||
"""
|
||||
all_controllers = server.controllers
|
||||
non_hba_controllers = [c for c in all_controllers
|
||||
if not c.properties.get('HBA Mode Enabled', False)]
|
||||
supported_controllers = [c for c in all_controllers if select_condition(c)]
|
||||
|
||||
if not non_hba_controllers:
|
||||
reason = ("None of the available HPSSA controllers %s have RAID "
|
||||
"enabled" % ', '.join([c.id for c in all_controllers]))
|
||||
if not supported_controllers:
|
||||
reason = ("None of the available SSA controllers %(controllers)s "
|
||||
"have %(msg)s"
|
||||
% {'controllers': ', '.join([c.id for c in all_controllers]),
|
||||
'msg': msg})
|
||||
raise exception.HPSSAOperationError(reason=reason)
|
||||
|
||||
server.controllers = non_hba_controllers
|
||||
server.controllers = supported_controllers
|
||||
|
||||
|
||||
def create_configuration(raid_config):
|
||||
@@ -117,7 +123,9 @@ def create_configuration(raid_config):
|
||||
"""
|
||||
server = objects.Server()
|
||||
|
||||
_filter_raid_mode_controllers(server)
|
||||
select_controllers = lambda x: not x.properties.get('HBA Mode Enabled',
|
||||
False)
|
||||
_select_controllers_by(server, select_controllers, 'RAID enabled')
|
||||
|
||||
validate(raid_config)
|
||||
|
||||
@@ -297,7 +305,9 @@ def delete_configuration():
|
||||
"""
|
||||
server = objects.Server()
|
||||
|
||||
_filter_raid_mode_controllers(server)
|
||||
select_controllers = lambda x: not x.properties.get('HBA Mode Enabled',
|
||||
False)
|
||||
_select_controllers_by(server, select_controllers, 'RAID enabled')
|
||||
|
||||
for controller in server.controllers:
|
||||
# Trigger delete only if there is some RAID array, otherwise
|
||||
@@ -337,3 +347,56 @@ def get_configuration():
|
||||
|
||||
_update_physical_disk_details(raid_config, server)
|
||||
return raid_config
|
||||
|
||||
|
||||
def has_erase_completed():
|
||||
server = objects.Server()
|
||||
drives = server.get_physical_drives()
|
||||
if any((drive.erase_status == 'Erase In Progress')
|
||||
for drive in drives):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def erase_devices():
|
||||
"""Erase all the drives on this server.
|
||||
|
||||
This method performs sanitize erase on all the supported physical drives
|
||||
in this server. This erase cannot be performed on logical drives.
|
||||
|
||||
:returns: a dictionary of controllers with drives and the erase status.
|
||||
:raises exception.HPSSAException, if none of the drives support
|
||||
sanitize erase.
|
||||
"""
|
||||
server = objects.Server()
|
||||
|
||||
select_controllers = lambda x: (x.properties.get(
|
||||
'Sanitize Erase Supported',
|
||||
False) == 'True')
|
||||
_select_controllers_by(server, select_controllers,
|
||||
'Sanitize Erase Supported')
|
||||
|
||||
for controller in server.controllers:
|
||||
drives = [x for x in controller.unassigned_physical_drives
|
||||
if (x.get_physical_drive_dict().get('erase_status', '')
|
||||
== 'OK')]
|
||||
if drives:
|
||||
drives = ','.join(x.id for x in drives)
|
||||
controller.erase_devices(drives)
|
||||
|
||||
common.wait_for_operation_to_complete(
|
||||
has_erase_completed,
|
||||
delay_bw_retries=300,
|
||||
failover_msg='Disk erase failed.'
|
||||
)
|
||||
|
||||
server.refresh()
|
||||
|
||||
status = {}
|
||||
for controller in server.controllers:
|
||||
drive_status = {x.id: x.erase_status
|
||||
for x in controller.unassigned_physical_drives}
|
||||
status[controller.id] = drive_status
|
||||
|
||||
return status
|
||||
|
||||
@@ -317,7 +317,12 @@ class Controller(object):
|
||||
self.unassigned_physical_drives = []
|
||||
self.raid_arrays = []
|
||||
|
||||
unassigned_drives = properties.get('unassigned', {})
|
||||
# This step is needed because of the mismatch in the data returned by
|
||||
# hpssacli and ssacli.
|
||||
attr = ''.join(x for x in properties
|
||||
if x == 'Unassigned' or x == 'unassigned')
|
||||
|
||||
unassigned_drives = properties.get(attr, {})
|
||||
for key, value in unassigned_drives.items():
|
||||
self.unassigned_physical_drives.append(PhysicalDrive(key,
|
||||
value,
|
||||
@@ -407,6 +412,15 @@ class Controller(object):
|
||||
"""
|
||||
self.execute_cmd("logicaldrive", "all", "delete", "forced")
|
||||
|
||||
def erase_devices(self, drive):
|
||||
cmd_args = []
|
||||
cmd_args.append("pd %s" % drive)
|
||||
cmd_args.extend(['modify', 'erase',
|
||||
'erasepattern=overwrite',
|
||||
'unrestricted=off',
|
||||
'forced'])
|
||||
self.execute_cmd(*cmd_args)
|
||||
|
||||
|
||||
class RaidArray(object):
|
||||
"""Class for a RAID Array.
|
||||
@@ -580,6 +594,7 @@ class PhysicalDrive:
|
||||
self.disk_type = constants.get_disk_type(ssa_interface)
|
||||
self.model = self.properties.get('Model')
|
||||
self.firmware = self.properties.get('Firmware Revision')
|
||||
self.erase_status = self.properties.get('Status')
|
||||
|
||||
def get_physical_drive_dict(self):
|
||||
"""Returns a dictionary of with the details of the physical drive."""
|
||||
@@ -598,4 +613,5 @@ class PhysicalDrive:
|
||||
'interface_type': self.interface_type,
|
||||
'model': self.model,
|
||||
'firmware': self.firmware,
|
||||
'status': status}
|
||||
'status': status,
|
||||
'erase_status': self.erase_status}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
from ironic_python_agent import hardware
|
||||
|
||||
from proliantutils import exception
|
||||
from proliantutils.hpssa import manager as hpssa_manager
|
||||
|
||||
|
||||
@@ -80,3 +81,21 @@ class ProliantHardwareManager(hardware.GenericHardwareManager):
|
||||
for the node
|
||||
"""
|
||||
return hpssa_manager.delete_configuration()
|
||||
|
||||
def erase_devices(self, node, port):
|
||||
"""Erase the drives on the bare metal.
|
||||
|
||||
This method erase all the drives which supports sanitize on
|
||||
bare metal. If fails, it falls back to the generic erase method.
|
||||
:returns: The dictionary of controllers with the drives and erase
|
||||
status for each drive.
|
||||
"""
|
||||
try:
|
||||
result = {}
|
||||
result['Sanitize Erase'] = hpssa_manager.erase_devices()
|
||||
|
||||
except exception.HPSSAOperationError:
|
||||
result.update(super(ProliantHardwareManager,
|
||||
self).erase_devices(node, port))
|
||||
|
||||
return result
|
||||
|
||||
@@ -2330,3 +2330,156 @@ Smart Array P822 in Slot 3
|
||||
Mount Points: None
|
||||
Sanitize Erase Supported: False
|
||||
'''
|
||||
|
||||
SSA_ERASE_DRIVE = '''
|
||||
|
||||
Smart Array P440 in Slot 2
|
||||
Bus Interface: PCI
|
||||
Slot: 2
|
||||
Serial Number: PDNMF0ARH8Y342
|
||||
RAID 6 (ADG) Status: Enabled
|
||||
Controller Status: OK
|
||||
Firmware Version: 4.52-0
|
||||
Spare Activation Mode: Activate on physical drive failure (default)
|
||||
Encryption: Disabled
|
||||
Driver Name: hpsa
|
||||
Driver Version: 3.4.16
|
||||
Controller Mode: RAID
|
||||
Pending Controller Mode: RAID
|
||||
Controller Mode Reboot: Not Required
|
||||
Host Serial Number: SGH537Y7AY
|
||||
Sanitize Erase Supported: True
|
||||
Primary Boot Volume: None
|
||||
Secondary Boot Volume: None
|
||||
|
||||
|
||||
Port Name: 1I
|
||||
Port ID: 0
|
||||
Port Connection Number: 0
|
||||
SAS Address: 5001438035544EC0
|
||||
Port Location: Internal
|
||||
Managed Cable Connected: False
|
||||
|
||||
|
||||
Internal Drive Cage at Port 1I, Box 0, OK
|
||||
|
||||
Power Supply Status: Not Redundant
|
||||
Drive Bays: 4
|
||||
Port: 1I
|
||||
Box: 0
|
||||
Location: Internal
|
||||
|
||||
Physical Drives
|
||||
None attached
|
||||
|
||||
|
||||
|
||||
Internal Drive Cage at Port 1I, Box 2, OK
|
||||
|
||||
Power Supply Status: Not Redundant
|
||||
Drive Bays: 4
|
||||
Port: 1I
|
||||
Box: 2
|
||||
Location: Internal
|
||||
|
||||
Physical Drives
|
||||
physicaldrive 1I:2:1 (port 1I:box 2:bay 1, SAS HDD, 300 GB, OK)
|
||||
|
||||
|
||||
|
||||
unassigned
|
||||
|
||||
physicaldrive 1I:2:1
|
||||
Port: 1I
|
||||
Box: 2
|
||||
Bay: 1
|
||||
Status: OK
|
||||
Drive Type: Unassigned Drive
|
||||
Interface Type: SAS
|
||||
Size: 300 GB
|
||||
Drive exposed to OS: False
|
||||
Logical/Physical Block Size: 512/512
|
||||
Rotational Speed: 15100
|
||||
Firmware Revision: HPD4
|
||||
Serial Number: S7K0C3FJ0000K601EZLM
|
||||
WWID: 5000C5008E183B1D
|
||||
Model: HP EH0300JEDHC
|
||||
Current Temperature (C): 42
|
||||
Maximum Temperature (C): 52
|
||||
PHY Count: 2
|
||||
PHY Transfer Rate: 12.0Gbps, Unknown
|
||||
Drive Authentication Status: OK
|
||||
Carrier Application Version: 11
|
||||
Carrier Bootloader Version: 6
|
||||
Sanitize Erase Supported: True
|
||||
Sanitize Estimated Max Erase Time: 0 hour(s)36 minute(s)
|
||||
Unrestricted Sanitize Supported: False
|
||||
Shingled Magnetic Recording Support: None
|
||||
'''
|
||||
|
||||
SSA_ERASE_IN_PROGRESS = '''
|
||||
Smart Array P440 in Slot 2
|
||||
Controller Mode: RAID
|
||||
Pending Controller Mode: RAID
|
||||
Sanitize Erase Supported: True
|
||||
Primary Boot Volume: None
|
||||
Secondary Boot Volume: None
|
||||
|
||||
Physical Drives
|
||||
physicaldrive 1I:2:1 (port 1I:box 2:bay 1, SAS HDD, 300 GB, OK)
|
||||
|
||||
|
||||
|
||||
unassigned
|
||||
|
||||
physicaldrive 1I:2:1
|
||||
Drive Type: Unassigned Drive
|
||||
Interface Type: SAS
|
||||
Size: 300 GB
|
||||
Status: Erase In Progress
|
||||
Drive Type: Unassigned Drive
|
||||
Sanitize Erase Supported: True
|
||||
Sanitize Estimated Max Erase Time: 0 hour(s)36 minute(s)
|
||||
Unrestricted Sanitize Supported: False
|
||||
'''
|
||||
|
||||
SSA_ERASE_COMPLETE = '''
|
||||
Smart Array P440 in Slot 2
|
||||
Controller Mode: RAID
|
||||
Pending Controller Mode: RAID
|
||||
Sanitize Erase Supported: True
|
||||
Primary Boot Volume: None
|
||||
Secondary Boot Volume: None
|
||||
|
||||
Physical Drives
|
||||
physicaldrive 1I:2:1 (port 1I:box 2:bay 1, SAS HDD, 300 GB, OK)
|
||||
|
||||
|
||||
|
||||
unassigned
|
||||
|
||||
physicaldrive 1I:2:1
|
||||
Drive Type: Unassigned Drive
|
||||
Interface Type: SAS
|
||||
Size: 300 GB
|
||||
Status: Erase Complete. Reenable Before Using.
|
||||
Drive Type: Unassigned Drive
|
||||
Sanitize Erase Supported: True
|
||||
Sanitize Estimated Max Erase Time: 0 hour(s)36 minute(s)
|
||||
Unrestricted Sanitize Supported: False
|
||||
'''
|
||||
|
||||
SSA_ERASE_NOT_SUPPORTED = '''
|
||||
|
||||
Smart Array P440 in Slot 2
|
||||
Controller Status: OK
|
||||
Firmware Version: 4.52-0
|
||||
Spare Activation Mode: Activate on physical drive failure (default)
|
||||
Controller Mode: RAID
|
||||
Pending Controller Mode: RAID
|
||||
Controller Mode Reboot: Not Required
|
||||
Sanitize Erase Supported: False
|
||||
Primary Boot Volume: None
|
||||
Secondary Boot Volume: None
|
||||
|
||||
'''
|
||||
|
||||
@@ -191,7 +191,7 @@ class ManagerTestCases(testtools.TestCase):
|
||||
raid_info = {'logical_disks': 'foo'}
|
||||
|
||||
msg = ("An error was encountered while doing hpssa configuration: None"
|
||||
" of the available HPSSA controllers Smart Array P822 in "
|
||||
" of the available SSA controllers Smart Array P822 in "
|
||||
"Slot 3 have RAID enabled")
|
||||
ex = self.assertRaises(exception.HPSSAOperationError,
|
||||
manager.create_configuration,
|
||||
@@ -373,7 +373,6 @@ class ManagerTestCases(testtools.TestCase):
|
||||
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'
|
||||
|
||||
@@ -406,7 +405,7 @@ class ManagerTestCases(testtools.TestCase):
|
||||
get_all_details_mock.return_value = drives
|
||||
|
||||
msg = ("An error was encountered while doing hpssa configuration: None"
|
||||
" of the available HPSSA controllers Smart Array P822 in "
|
||||
" of the available SSA controllers Smart Array P822 in "
|
||||
"Slot 3 have RAID enabled")
|
||||
ex = self.assertRaises(exception.HPSSAOperationError,
|
||||
manager.delete_configuration)
|
||||
@@ -454,28 +453,82 @@ class ManagerTestCases(testtools.TestCase):
|
||||
self.assertEqual(sorted(pds_active_expected), sorted(pds_active))
|
||||
self.assertEqual(sorted(pds_ready_expected), sorted(pds_ready))
|
||||
|
||||
def test__filter_raid_mode_controllers_hba(self, get_all_details_mock):
|
||||
def test__select_controllers_by_hba(self, get_all_details_mock):
|
||||
get_all_details_mock.return_value = raid_constants.HPSSA_HBA_MODE
|
||||
|
||||
server = objects.Server()
|
||||
select_controllers = lambda x: not x.properties.get('HBA Mode Enabled',
|
||||
False)
|
||||
|
||||
msg = ("An error was encountered while doing hpssa configuration: None"
|
||||
" of the available HPSSA controllers Smart Array P822 in "
|
||||
"Slot 3 have RAID enabled")
|
||||
msg = ("An error was encountered while doing hpssa configuration: "
|
||||
"None of the available SSA controllers Smart Array P822 in "
|
||||
"Slot 3 have Raid enabled.")
|
||||
ex = self.assertRaises(exception.HPSSAOperationError,
|
||||
manager._filter_raid_mode_controllers,
|
||||
server)
|
||||
manager._select_controllers_by,
|
||||
server, select_controllers, 'Raid enabled')
|
||||
self.assertIn(msg, str(ex))
|
||||
|
||||
def test__filter_raid_mode_controllers(self, get_all_details_mock):
|
||||
def test__select_controllers_by(self, get_all_details_mock):
|
||||
get_all_details_mock.return_value = raid_constants.HPSSA_NO_DRIVES
|
||||
|
||||
server = objects.Server()
|
||||
select_controllers = lambda x: not x.properties.get('HBA Mode Enabled',
|
||||
False)
|
||||
ctrl_expected = server.controllers
|
||||
|
||||
manager._filter_raid_mode_controllers(server)
|
||||
manager._select_controllers_by(server, select_controllers,
|
||||
'Raid enabled')
|
||||
self.assertEqual(ctrl_expected, server.controllers)
|
||||
|
||||
@mock.patch.object(objects.Controller, 'execute_cmd')
|
||||
def test_erase_devices(self, controller_exec_cmd_mock,
|
||||
get_all_details_mock):
|
||||
erase_drive = raid_constants.SSA_ERASE_DRIVE
|
||||
erase_complete = raid_constants.SSA_ERASE_COMPLETE
|
||||
cmd_args = []
|
||||
cmd_args.append("pd 1I:2:1")
|
||||
cmd_args.extend(['modify', 'erase',
|
||||
'erasepattern=overwrite',
|
||||
'unrestricted=off',
|
||||
'forced'])
|
||||
expt_ret = {
|
||||
'Smart Array P440 in Slot 2': {
|
||||
'1I:2:1': 'Erase Complete. Reenable Before Using.'}}
|
||||
get_all_details_mock.side_effect = [erase_drive, erase_complete,
|
||||
erase_complete]
|
||||
|
||||
ret = manager.erase_devices()
|
||||
self.assertTrue(controller_exec_cmd_mock.called)
|
||||
controller_exec_cmd_mock.assert_any_call(*cmd_args)
|
||||
self.assertEqual(expt_ret, ret)
|
||||
|
||||
@mock.patch.object(objects.Controller, 'execute_cmd')
|
||||
def test_erase_devices_no_drives(self, controller_exec_cmd_mock,
|
||||
get_all_details_mock):
|
||||
erase_no_drives = raid_constants.SSA_ERASE_NOT_SUPPORTED
|
||||
get_all_details_mock.side_effect = [erase_no_drives]
|
||||
ex = self.assertRaises(exception.HPSSAOperationError,
|
||||
manager.erase_devices)
|
||||
expt_ret = ("None of the available SSA controllers Smart "
|
||||
"Array P440 in Slot 2 have Sanitize Erase Supported.")
|
||||
self.assertIn(expt_ret, str(ex))
|
||||
|
||||
@mock.patch.object(objects.Controller, 'execute_cmd')
|
||||
def test_erase_devices_in_progress(self, controller_exec_cmd_mock,
|
||||
get_all_details_mock):
|
||||
erase_progress = raid_constants.SSA_ERASE_IN_PROGRESS
|
||||
erase_complete = raid_constants.SSA_ERASE_COMPLETE
|
||||
|
||||
expt_ret = {
|
||||
'Smart Array P440 in Slot 2': {
|
||||
'1I:2:1': 'Erase Complete. Reenable Before Using.'}}
|
||||
get_all_details_mock.side_effect = [erase_progress, erase_complete,
|
||||
erase_complete]
|
||||
|
||||
ret = manager.erase_devices()
|
||||
self.assertFalse(controller_exec_cmd_mock.called)
|
||||
self.assertEqual(expt_ret, ret)
|
||||
|
||||
|
||||
class RaidConfigValidationTestCases(testtools.TestCase):
|
||||
|
||||
|
||||
@@ -337,6 +337,18 @@ class ControllerTest(testtools.TestCase):
|
||||
|
||||
self.assertIsNone(controller.get_physical_drive_by_id('foo'))
|
||||
|
||||
@mock.patch.object(objects.Controller, 'execute_cmd')
|
||||
def test_erase_devices(self, execute_mock,
|
||||
get_all_details_mock):
|
||||
get_all_details_mock.return_value = raid_constants.SSA_ERASE_DRIVE
|
||||
server = objects.Server()
|
||||
controller = server.controllers[0]
|
||||
controller.erase_devices('1I:2:1')
|
||||
execute_mock.assert_called_once_with('pd 1I:2:1', 'modify', 'erase',
|
||||
'erasepattern=overwrite',
|
||||
'unrestricted=off',
|
||||
'forced')
|
||||
|
||||
|
||||
@mock.patch.object(objects.Server, '_get_all_details')
|
||||
class LogicalDriveTest(testtools.TestCase):
|
||||
@@ -516,6 +528,8 @@ class PhysicalDriveTest(testtools.TestCase):
|
||||
self.assertEqual('ssd', ret_sata['disk_type'])
|
||||
self.assertEqual('sata', ret_sata['interface_type'])
|
||||
|
||||
self.assertEqual('OK', ret_sata['erase_status'])
|
||||
|
||||
def test_get_physical_drive_dict_part_of_array(self, get_all_details_mock):
|
||||
|
||||
get_all_details_mock.return_value = raid_constants.HPSSA_ONE_DRIVE
|
||||
@@ -532,6 +546,7 @@ class PhysicalDriveTest(testtools.TestCase):
|
||||
self.assertEqual('HP EF0600FARNA', ret['model'])
|
||||
self.assertEqual('HPD6', ret['firmware'])
|
||||
self.assertEqual('active', ret['status'])
|
||||
self.assertEqual('OK', ret['erase_status'])
|
||||
|
||||
def test_get_physical_drive_dict_unassigned(self, get_all_details_mock):
|
||||
|
||||
@@ -549,6 +564,7 @@ class PhysicalDriveTest(testtools.TestCase):
|
||||
self.assertEqual('HP EF0600FARNA', ret['model'])
|
||||
self.assertEqual('HPD6', ret['firmware'])
|
||||
self.assertEqual('ready', ret['status'])
|
||||
self.assertEqual('OK', ret['erase_status'])
|
||||
|
||||
|
||||
class PrivateMethodsTestCase(testtools.TestCase):
|
||||
|
||||
@@ -24,5 +24,6 @@ if not ironic_python_agent:
|
||||
sys.modules['ironic_python_agent.errors'] = ipa_mock.errors
|
||||
sys.modules['ironic_python_agent.hardware'] = ipa_mock.hardware
|
||||
ipa_mock.hardware.GenericHardwareManager = mock.MagicMock
|
||||
mock.MagicMock.erase_devices = mock.MagicMock(name='erase_devices')
|
||||
if 'proliantutils.ipa_hw_manager' in sys.modules:
|
||||
reload(sys.modules['proliantutils.ipa_hw_manager'])
|
||||
|
||||
@@ -13,11 +13,15 @@
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
from oslo_utils import importutils
|
||||
import testtools
|
||||
|
||||
from proliantutils import exception
|
||||
from proliantutils.hpssa import manager as hpssa_manager
|
||||
from proliantutils.ipa_hw_manager import hardware_manager
|
||||
|
||||
ironic_python_agent = importutils.try_import('ironic_python_agent')
|
||||
|
||||
|
||||
class ProliantHardwareManagerTestCase(testtools.TestCase):
|
||||
|
||||
@@ -50,3 +54,31 @@ class ProliantHardwareManagerTestCase(testtools.TestCase):
|
||||
ret = self.hardware_manager.delete_configuration("", "")
|
||||
delete_mock.assert_called_once_with()
|
||||
self.assertEqual('current-config', ret)
|
||||
|
||||
@mock.patch.object(hpssa_manager, 'erase_devices')
|
||||
def test_erase_devices(self, erase_mock):
|
||||
node = {}
|
||||
port = {}
|
||||
erase_mock.return_value = 'erase_status'
|
||||
ret = self.hardware_manager.erase_devices(node, port)
|
||||
erase_mock.assert_called_once_with()
|
||||
self.assertEqual({'Sanitize Erase': 'erase_status'}, ret)
|
||||
|
||||
@mock.patch.object(ironic_python_agent.hardware.GenericHardwareManager,
|
||||
'erase_devices')
|
||||
@mock.patch.object(hpssa_manager, 'erase_devices')
|
||||
def test_erase_devices_not_supported(self, erase_mock, generic_erase_mock):
|
||||
node = {}
|
||||
port = {}
|
||||
value = ("Sanitize erase not supported in the "
|
||||
"available controllers")
|
||||
e = exception.HPSSAOperationError(value)
|
||||
erase_mock.side_effect = e
|
||||
generic_erase_mock.return_value = {'foo': 'bar'}
|
||||
expt_return = {
|
||||
'Sanitize Erase': erase_mock.side_effect}
|
||||
expt_return.update(generic_erase_mock.return_value)
|
||||
|
||||
self.hardware_manager.erase_devices(node, port)
|
||||
|
||||
generic_erase_mock.assert_called_once_with(node, port)
|
||||
|
||||
Reference in New Issue
Block a user