Merge "Try to unlock failed device before proceeding"
This commit is contained in:
@@ -889,6 +889,31 @@ class GenericHardwareManager(HardwareManager):
|
|||||||
return security_lines
|
return security_lines
|
||||||
|
|
||||||
def _ata_erase(self, block_device):
|
def _ata_erase(self, block_device):
|
||||||
|
|
||||||
|
def __attempt_unlock_drive(block_device, security_lines=None):
|
||||||
|
# Attempt to unlock the drive in the event it has already been
|
||||||
|
# locked by a previous failed attempt. We try the empty string as
|
||||||
|
# versions of hdparm < 9.51, interpreted NULL as the literal
|
||||||
|
# string, "NULL", as opposed to the empty string.
|
||||||
|
if not security_lines:
|
||||||
|
security_lines = self._get_ata_security_lines(block_device)
|
||||||
|
unlock_passwords = ['NULL', '']
|
||||||
|
for password in unlock_passwords:
|
||||||
|
if 'not locked' in security_lines:
|
||||||
|
break
|
||||||
|
try:
|
||||||
|
utils.execute('hdparm', '--user-master', 'u',
|
||||||
|
'--security-unlock', password,
|
||||||
|
block_device.name)
|
||||||
|
except processutils.ProcessExecutionError as e:
|
||||||
|
LOG.info('Security unlock failed for device '
|
||||||
|
'%(name)s using password "%(password)s": %(err)s',
|
||||||
|
{'name': block_device.name,
|
||||||
|
'password': password,
|
||||||
|
'err': e})
|
||||||
|
security_lines = self._get_ata_security_lines(block_device)
|
||||||
|
return security_lines
|
||||||
|
|
||||||
security_lines = self._get_ata_security_lines(block_device)
|
security_lines = self._get_ata_security_lines(block_device)
|
||||||
|
|
||||||
# If secure erase isn't supported return False so erase_block_device
|
# If secure erase isn't supported return False so erase_block_device
|
||||||
@@ -907,26 +932,8 @@ class GenericHardwareManager(HardwareManager):
|
|||||||
).format(block_device.name))
|
).format(block_device.name))
|
||||||
|
|
||||||
# At this point, we could be in SEC1,4,5
|
# At this point, we could be in SEC1,4,5
|
||||||
|
# Attempt to unlock the drive if it has failed in a prior attempt.
|
||||||
# Attempt to unlock the drive in the event it has already been
|
security_lines = __attempt_unlock_drive(block_device, security_lines)
|
||||||
# locked by a previous failed attempt. We try the empty string as
|
|
||||||
# versions of hdparm < 9.51, interpreted NULL as the literal string,
|
|
||||||
# "NULL", as opposed to the empty string.
|
|
||||||
unlock_passwords = ['NULL', '']
|
|
||||||
for password in unlock_passwords:
|
|
||||||
if 'not locked' in security_lines:
|
|
||||||
break
|
|
||||||
try:
|
|
||||||
utils.execute('hdparm', '--user-master', 'u',
|
|
||||||
'--security-unlock', password,
|
|
||||||
block_device.name)
|
|
||||||
except processutils.ProcessExecutionError as e:
|
|
||||||
LOG.info('Security unlock failed for device '
|
|
||||||
'%(name)s using password "%(password)s": %(err)s',
|
|
||||||
{'name': block_device.name,
|
|
||||||
'password': password,
|
|
||||||
'err': e})
|
|
||||||
security_lines = self._get_ata_security_lines(block_device)
|
|
||||||
|
|
||||||
# If the unlock failed we will still be in SEC4, otherwise, we will be
|
# If the unlock failed we will still be in SEC4, otherwise, we will be
|
||||||
# in SEC1 or SEC5
|
# in SEC1 or SEC5
|
||||||
@@ -959,6 +966,10 @@ class GenericHardwareManager(HardwareManager):
|
|||||||
utils.execute('hdparm', '--user-master', 'u', erase_option,
|
utils.execute('hdparm', '--user-master', 'u', erase_option,
|
||||||
'NULL', block_device.name)
|
'NULL', block_device.name)
|
||||||
except processutils.ProcessExecutionError as e:
|
except processutils.ProcessExecutionError as e:
|
||||||
|
# NOTE(TheJulia): Attempt unlock to allow fallback to shred
|
||||||
|
# to occur, otherwise shred will fail as well, as the security
|
||||||
|
# mode will prevent IO operations to the disk.
|
||||||
|
__attempt_unlock_drive(block_device)
|
||||||
raise errors.BlockDeviceEraseError('Erase failed for device '
|
raise errors.BlockDeviceEraseError('Erase failed for device '
|
||||||
'%(name)s: %(err)s' %
|
'%(name)s: %(err)s' %
|
||||||
{'name': block_device.name,
|
{'name': block_device.name,
|
||||||
|
@@ -1576,11 +1576,15 @@ class TestGenericHardwareManager(base.IronicAgentTest):
|
|||||||
# Exception on security erase
|
# Exception on security erase
|
||||||
hdparm_output = create_hdparm_info(
|
hdparm_output = create_hdparm_info(
|
||||||
supported=True, enabled=False, frozen=False, enhanced_erase=False)
|
supported=True, enabled=False, frozen=False, enhanced_erase=False)
|
||||||
|
hdparm_unlocked_output = create_hdparm_info(
|
||||||
|
supported=True, locked=True, frozen=False, enhanced_erase=False)
|
||||||
mocked_execute.side_effect = [
|
mocked_execute.side_effect = [
|
||||||
(hdparm_output, '', '-1'),
|
(hdparm_output, '', '-1'),
|
||||||
'', # security-set-pass
|
'', # security-set-pass
|
||||||
processutils.ProcessExecutionError() # security-erase
|
processutils.ProcessExecutionError(), # security-erase
|
||||||
|
(hdparm_unlocked_output, '', '-1'),
|
||||||
|
'', # attempt security unlock
|
||||||
|
(hdparm_output, '', '-1')
|
||||||
]
|
]
|
||||||
|
|
||||||
block_device = hardware.BlockDevice('/dev/sda', 'big', 1073741824,
|
block_device = hardware.BlockDevice('/dev/sda', 'big', 1073741824,
|
||||||
|
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Fixes the ATA Secure Erase logic to attempt an immediate unlock in the
|
||||||
|
event of a failed attempt to Secure Erase. This is required to permit
|
||||||
|
fallback to make use of the ``shred`` disk utility.
|
||||||
|
|
||||||
|
In the event that an ATA Secure Erase operation fails during cleaning,
|
||||||
|
the disk will be write locked. In this case, the disk must be explicitly
|
||||||
|
unlocked.
|
||||||
|
|
||||||
|
This should also prevent failures where an ATA Secure Erase operation
|
||||||
|
fails with a pass-through disk controller, which may prevent the disk
|
||||||
|
from being available after a reboot operation. For additional information,
|
||||||
|
please see
|
||||||
|
`story 2002546 <https://storyboard.openstack.org/#!/story/2002546>`_.
|
Reference in New Issue
Block a user