summaryrefslogtreecommitdiff
path: root/ironic_python_agent
diff options
context:
space:
mode:
authorJay Faulkner <jay@jvf.cc>2015-03-17 16:26:06 -0700
committerJay Faulkner <jay@jvf.cc>2015-03-18 14:57:28 -0700
commita17c82428842fe4994977ed6896bc99da8acf41a (patch)
tree7436ea08b027e0c86d57d1fd78df4190c1c00c83 /ironic_python_agent
parentac4e9901d688a6efd39ddc9b20c724e6b24082bf (diff)
downloadironic-python-agent-a17c82428842fe4994977ed6896bc99da8acf41a.tar.gz
Add fallback secure erase using shred
This prevents devices from failing cleaning if they don't support ATA security erase. Instead, the device will be erased by overwriting using GNU shred. Change-Id: Ie4f88b97c8c34efe2397538662622abd0b963aea
Diffstat (limited to 'ironic_python_agent')
-rw-r--r--ironic_python_agent/hardware.py17
-rw-r--r--ironic_python_agent/tests/hardware.py49
2 files changed, 52 insertions, 14 deletions
diff --git a/ironic_python_agent/hardware.py b/ironic_python_agent/hardware.py
index 96c65127..8b5b94d9 100644
--- a/ironic_python_agent/hardware.py
+++ b/ironic_python_agent/hardware.py
@@ -357,11 +357,28 @@ class GenericHardwareManager(HardwareManager):
if self._ata_erase(block_device):
return
+ if self._shred_block_device(block_device):
+ return
+
msg = ('Unable to erase block device {0}: device is unsupported.'
).format(block_device.name)
LOG.error(msg)
raise errors.IncompatibleHardwareMethodError(msg)
+ def _shred_block_device(self, block_device):
+ """Erase a block device using shred.
+
+ :param block_device: a BlockDevice object to be erased
+ :returns: True if the erase succeeds, False if it fails for any reason
+ """
+ try:
+ utils.execute('shred', '--force', '--zero', '--verbose',
+ '--iterations', '1', block_device.name)
+ except errors.ProcessExecutionError:
+ return False
+
+ return True
+
def _get_ata_security_lines(self, block_device):
output = utils.execute('hdparm', '-I', block_device.name)[0]
diff --git a/ironic_python_agent/tests/hardware.py b/ironic_python_agent/tests/hardware.py
index 60a1899a..000c2076 100644
--- a/ironic_python_agent/tests/hardware.py
+++ b/ironic_python_agent/tests/hardware.py
@@ -125,6 +125,19 @@ BLK_DEVICE_TEMPLATE = (
'KNAME="loop0" MODEL="" SIZE="109109248" ROTA="1" TYPE="loop"'
)
+SHRED_OUTPUT = (
+ 'shred: /dev/sda: pass 1/2 (random)...\n'
+ 'shred: /dev/sda: pass 1/2 (random)...4.9GiB/29GiB 17%\n'
+ 'shred: /dev/sda: pass 1/2 (random)...15GiB/29GiB 51%\n'
+ 'shred: /dev/sda: pass 1/2 (random)...20GiB/29GiB 69%\n'
+ 'shred: /dev/sda: pass 1/2 (random)...29GiB/29GiB 100%\n'
+ 'shred: /dev/sda: pass 2/2 (000000)...\n'
+ 'shred: /dev/sda: pass 2/2 (000000)...4.9GiB/29GiB 17%\n'
+ 'shred: /dev/sda: pass 2/2 (000000)...15GiB/29GiB 51%\n'
+ 'shred: /dev/sda: pass 2/2 (000000)...20GiB/29GiB 69%\n'
+ 'shred: /dev/sda: pass 2/2 (000000)...29GiB/29GiB 100%\n'
+)
+
class FakeHardwareManager(hardware.GenericHardwareManager):
def __init__(self, hardware_support):
@@ -401,37 +414,45 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
])
@mock.patch.object(utils, 'execute')
- def test_erase_block_device_ata_nosecurity(self, mocked_execute):
+ def test_erase_block_device_nosecurity_shred(self, mocked_execute):
hdparm_output = HDPARM_INFO_TEMPLATE.split('\nSecurity:')[0]
mocked_execute.side_effect = [
- (hdparm_output, '')
+ (hdparm_output, ''),
+ (SHRED_OUTPUT, '')
]
block_device = hardware.BlockDevice('/dev/sda', 'big', 1073741824,
True)
- self.assertRaises(errors.IncompatibleHardwareMethodError,
- self.hardware.erase_block_device,
- block_device)
+ self.hardware.erase_block_device(block_device)
+ mocked_execute.assert_has_calls([
+ mock.call('hdparm', '-I', '/dev/sda'),
+ mock.call('shred', '--force', '--zero', '--verbose',
+ '--iterations', '1', '/dev/sda')
+ ])
@mock.patch.object(utils, 'execute')
- def test_erase_block_device_ata_not_supported(self, mocked_execute):
+ def test_erase_block_device_notsupported_shred(self, mocked_execute):
hdparm_output = HDPARM_INFO_TEMPLATE % {
- 'supported': 'not\tsupported',
- 'enabled': 'not\tenabled',
- 'frozen': 'not\tfrozen',
- 'enhanced_erase': 'not\tsupported: enhanced erase',
+ 'supported': 'not\tsupported',
+ 'enabled': 'not\tenabled',
+ 'frozen': 'not\tfrozen',
+ 'enhanced_erase': 'not\tsupported: enhanced erase',
}
mocked_execute.side_effect = [
- (hdparm_output, '')
+ (hdparm_output, ''),
+ (SHRED_OUTPUT, '')
]
block_device = hardware.BlockDevice('/dev/sda', 'big', 1073741824,
True)
- self.assertRaises(errors.IncompatibleHardwareMethodError,
- self.hardware.erase_block_device,
- block_device)
+ self.hardware.erase_block_device(block_device)
+ mocked_execute.assert_has_calls([
+ mock.call('hdparm', '-I', '/dev/sda'),
+ mock.call('shred', '--force', '--zero', '--verbose',
+ '--iterations', '1', '/dev/sda')
+ ])
@mock.patch.object(utils, 'execute')
def test_erase_block_device_ata_security_enabled(self, mocked_execute):