From b4cc3050dbda8d693fe0d36da30a44385b64a2be Mon Sep 17 00:00:00 2001
From: Clif Houck <me@clifhouck.com>
Date: Thu, 5 Feb 2015 17:03:33 -0600
Subject: [PATCH] Added support for secure erase enhanced

Added support for secure erase enhanced option when doing an ATA secure erase.

Also made it prefer the enhanced version if hdparm claims the device
supports it.

Change-Id: I2ce04d0b967d6c176acd40ea10a05bcab5dbf2d0
---
 ironic_python_agent/hardware.py       |  8 +++++-
 ironic_python_agent/tests/hardware.py | 39 ++++++++++++++++++++++++++-
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/ironic_python_agent/hardware.py b/ironic_python_agent/hardware.py
index d7e0fd510..2ead58c14 100644
--- a/ironic_python_agent/hardware.py
+++ b/ironic_python_agent/hardware.py
@@ -314,7 +314,13 @@ class GenericHardwareManager(HardwareManager):
 
         utils.execute('hdparm', '--user-master', 'u', '--security-set-pass',
                       'NULL', block_device.name)
-        utils.execute('hdparm', '--user-master', 'u', '--security-erase',
+
+        # Use the 'enhanced' security erase option if it's supported.
+        erase_option = '--security-erase'
+        if 'not supported: enhanced erase' not in security_lines:
+            erase_option += '-enhanced'
+
+        utils.execute('hdparm', '--user-master', 'u', erase_option,
                       'NULL', block_device.name)
 
         # Verify that security is now 'not enabled'
diff --git a/ironic_python_agent/tests/hardware.py b/ironic_python_agent/tests/hardware.py
index fa107d10b..e37c0e51c 100644
--- a/ironic_python_agent/tests/hardware.py
+++ b/ironic_python_agent/tests/hardware.py
@@ -106,7 +106,7 @@ HDPARM_INFO_TEMPLATE = (
     '\tnot\tlocked\n'
     '\t%(frozen)s\n'
     '\tnot\texpired: security count\n'
-    '\t\tsupported: enhanced erase\n'
+    '\t%(enhanced_erase)s\n'
     '\t24min for SECURITY ERASE UNIT. 24min for ENHANCED SECURITY '
         'ERASE UNIT.\n'
     'Checksum: correct\n'
@@ -323,6 +323,7 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
             'supported': '\tsupported',
             'enabled': 'not\tenabled',
             'frozen': 'not\tfrozen',
+            'enhanced_erase': 'not\tsupported: enhanced erase',
         }
         mocked_execute.side_effect = [
             (HDPARM_INFO_TEMPLATE % hdparm_info_fields, ''),
@@ -363,6 +364,7 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
             'supported': 'not\tsupported',
             'enabled': 'not\tenabled',
             'frozen': 'not\tfrozen',
+            'enhanced_erase': 'not\tsupported: enhanced erase',
         }
 
         mocked_execute.side_effect = [
@@ -381,6 +383,7 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
             'supported': '\tsupported',
             'enabled': '\tenabled',
             'frozen': 'not\tfrozen',
+            'enhanced_erase': 'not\tsupported: enhanced erase',
         }
 
         mocked_execute.side_effect = [
@@ -399,6 +402,7 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
             'supported': '\tsupported',
             'enabled': 'not\tenabled',
             'frozen': '\tfrozen',
+            'enhanced_erase': 'not\tsupported: enhanced erase',
         }
 
         mocked_execute.side_effect = [
@@ -417,6 +421,7 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
             'supported': '\tsupported',
             'enabled': 'not\tenabled',
             'frozen': 'not\tfrozen',
+            'enhanced_erase': 'not\tsupported: enhanced erase',
         }
 
         # If security mode remains enabled after the erase, it is indiciative
@@ -425,6 +430,7 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
             'supported': '\tsupported',
             'enabled': '\tenabled',
             'frozen': 'not\tfrozen',
+            'enhanced_erase': 'not\tsupported: enhanced erase',
         }
 
         mocked_execute.side_effect = [
@@ -439,3 +445,34 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
         self.assertRaises(errors.BlockDeviceEraseError,
                           self.hardware.erase_block_device,
                           block_device)
+
+    def test_normal_vs_enhanced_security_erase(self):
+        @mock.patch.object(utils, 'execute')
+        def test_security_erase_option(test_case,
+                                       enhanced_erase_string,
+                                       expected_option,
+                                       mocked_execute):
+            hdparm_parameters = {
+                'supported': '\tsupported',
+                'enabled': 'not\tenabled',
+                'frozen': 'not\tfrozen',
+                'enhanced_erase': enhanced_erase_string,
+            }
+            mocked_execute.side_effect = [
+                (HDPARM_INFO_TEMPLATE % hdparm_parameters, ''),
+                ('', ''),
+                ('', ''),
+                (HDPARM_INFO_TEMPLATE % hdparm_parameters, ''),
+            ]
+
+            block_device = hardware.BlockDevice('/dev/sda', 'big', 1073741824,
+                                                True)
+            test_case.hardware.erase_block_device(block_device)
+            mocked_execute.assert_any_call('hdparm', '--user-master', 'u',
+                                           expected_option,
+                                           'NULL', '/dev/sda')
+
+        test_security_erase_option(self,
+                '\tsupported: enhanced erase', '--security-erase-enhanced')
+        test_security_erase_option(self,
+                '\tnot\tsupported: enhanced erase', '--security-erase')