diff --git a/doc/source/admin/drivers/ilo.rst b/doc/source/admin/drivers/ilo.rst index 064318a5ff..a6db21afc5 100644 --- a/doc/source/admin/drivers/ilo.rst +++ b/doc/source/admin/drivers/ilo.rst @@ -61,6 +61,7 @@ features: * `Out of Band RAID Support`_ * `Out of Band Sanitize Disk Erase Support`_ +* `Out of Band One Button Secure Erase Support`_ Hardware interfaces ^^^^^^^^^^^^^^^^^^^ @@ -2008,9 +2009,57 @@ The default erase pattern are, for HDD, 'overwrite' and for SSD, 'block'. 9 hours and 300GB SSD with default pattern "block" would take approx. 30 seconds to complete the erase. +Out of Band One Button Secure Erase Support +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With Gen10 HPE Proliant servers which have been updated with SPP version 2019.03.0 +or later the ``ilo5`` hardware type supports firmware based one button secure erase +as a clean step. + +The One Button Secure Erase resets iLO and deletes all licenses stored there, resets +BIOS settings, and deletes all Active Health System (AHS) and warranty data stored on +the system. It also erases supported non-volatile storage data and deletes any +deployment settings profiles. See `HPE Gen10 Security Reference Guide`_ for more +information. + +Below are the steps to perform this clean step: + +* Perform the cleaning using 'one_button_secure_erase' clean step + +.. code-block:: console + + openstack baremetal node clean test_node --clean-steps\ + '[{"interface": "management", "step": "one_button_secure_erase"}]' + +* Once the clean step would triggered and node go to 'clean wait' state and + 'maintenance' flag on node would be set to 'True', then delete the node + +.. code-block:: console + + openstack baremetal node delete test_node + +.. note:: + * Even after deleting the node, One Button Secure Erase operation would continue + on the node. + + * This clean step should be kept last if the multiple clean steps are to be executed. + No clean step after this step would be executed. + + * One Button Secure Erase should be used with extreme caution, and only when a system + is being decommissioned. During the erase the iLO network would keep disconnecting + and after the erase user will completly lose iLO access along with the credentials + of the server, which needs to be regained by the administrator. The process can take + up to a day or two to fully erase and reset all user data. + + * When you activate One Button Secure Erase, iLO 5 does not allow firmware update + or reset operations. + +.. note:: + Do not perform any iLO 5 configuration changes until this process is completed. + .. _`ssacli documentation`: https://support.hpe.com/hpsc/doc/public/display?docId=c03909334 .. _`proliant-tools`: https://docs.openstack.org/diskimage-builder/latest/elements/proliant-tools/README.html .. _`HPE iLO4 User Guide`: https://h20566.www2.hpe.com/hpsc/doc/public/display?docId=c03334051 +.. _`HPE Gen10 Security Reference Guide`: https://support.hpe.com/hpesc/public/docDisplay?docLocale=en_US&docId=a00018320en_us .. _`iLO 4 management engine`: https://www.hpe.com/us/en/servers/integrated-lights-out-ilo.html .. _`iLO 5 management engine`: https://www.hpe.com/us/en/servers/integrated-lights-out-ilo.html#innovations .. _`Redfish`: https://www.dmtf.org/standards/redfish diff --git a/driver-requirements.txt b/driver-requirements.txt index 539d27ba99..495dcbfe32 100644 --- a/driver-requirements.txt +++ b/driver-requirements.txt @@ -4,7 +4,7 @@ # python projects they should package as optional dependencies for Ironic. # These are available on pypi -proliantutils>=2.9.5 +proliantutils>=2.10.0 pysnmp>=4.3.0,<5.0.0 python-scciclient>=0.8.0 python-dracclient>=3.1.0,<5.0.0 diff --git a/ironic/drivers/modules/ilo/management.py b/ironic/drivers/modules/ilo/management.py index 75b5934ea9..7c96f355b8 100644 --- a/ironic/drivers/modules/ilo/management.py +++ b/ironic/drivers/modules/ilo/management.py @@ -792,9 +792,6 @@ class Ilo5Management(IloManagement): task.node.save() def _set_clean_failed(self, task, msg): - LOG.error("Out-of-band sanitize disk erase job failed for node " - "%(node)s. Message: '%(message)s'.", - {'node': task.node.uuid, 'message': msg}) task.node.last_error = msg task.process_event('fail') @@ -927,9 +924,43 @@ class Ilo5Management(IloManagement): LOG.info("No drive found to perform out-of-band sanitize " "disk erase for node %(node)s", {'node': node.uuid}) except ilo_error.IloError as ilo_exception: + LOG.error("Out-of-band sanitize disk erase job failed for node " + "%(node)s. Message: '%(message)s'.", + {'node': task.node.uuid, 'message': ilo_exception}) self._pop_driver_internal_values(task, 'ilo_disk_erase_hdd_check', 'ilo_disk_erase_ssd_check', 'cleaning_reboot', 'skip_current_clean_step') self._set_clean_failed(task, ilo_exception) + + @base.clean_step(priority=0, abortable=False) + def one_button_secure_erase(self, task): + """Erase the whole system securely. + + The One-button secure erase process resets iLO and deletes all licenses + stored there, resets BIOS settings, and deletes all Active Health + System (AHS) and warranty data stored on the system. It also erases + supported non-volatile storage data and deletes any deployment settings + profiles. + + :param task: a TaskManager instance. + :raises: IloError on an error from iLO. + """ + node = task.node + LOG.info("Calling one button secure erase for node %(node)s", + {'node': node.uuid}) + try: + ilo_object = ilo_common.get_ilo_object(node) + ilo_object.do_one_button_secure_erase() + manager_utils.node_power_action(task, states.REBOOT) + node.maintenance = True + node.maintenance_reason = ( + "Running one button secure erase clean step.") + node.save() + return states.CLEANWAIT + except ilo_error.IloError as ilo_exception: + LOG.error("One button secure erase job failed for node " + "%(node)s. Message: '%(message)s'.", + {'node': task.node.uuid, 'message': ilo_exception}) + self._set_clean_failed(task, ilo_exception) diff --git a/ironic/tests/unit/drivers/modules/ilo/test_management.py b/ironic/tests/unit/drivers/modules/ilo/test_management.py index 684c50c362..76cebb0c92 100644 --- a/ironic/tests/unit/drivers/modules/ilo/test_management.py +++ b/ironic/tests/unit/drivers/modules/ilo/test_management.py @@ -1669,11 +1669,12 @@ class Ilo5ManagementTestCase(db_base.DbTestCase): task.driver.management.erase_devices, task, erase_pattern={'ssd': 'xyz'}) + @mock.patch.object(ilo_management.LOG, 'error', autospec=True) @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) @mock.patch.object(ilo_management.Ilo5Management, '_set_clean_failed', autospec=True) def test_erase_devices_hdd_ilo_error(self, set_clean_failed_mock, - ilo_mock): + ilo_mock, log_mock): ilo_mock_object = ilo_mock.return_value ilo_mock_object.get_available_disk_types.return_value = ['HDD'] exc = ilo_error.IloError('error') @@ -1691,5 +1692,43 @@ class Ilo5ManagementTestCase(db_base.DbTestCase): task.node.driver_internal_info) self.assertNotIn('skip_current_clean_step', task.node.driver_internal_info) + self.assertTrue(log_mock.called) set_clean_failed_mock.assert_called_once_with( mock.ANY, task, exc) + + @mock.patch.object(manager_utils, 'node_power_action', autospec=True) + @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) + def test_one_button_secure_erase(self, ilo_mock, mock_power): + ilo_mock_object = ilo_mock.return_value + self.node.clean_step = {'step': 'one_button_secure_erase', + 'interface': 'management'} + self.node.save() + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + result = task.driver.management.one_button_secure_erase(task) + self.assertTrue( + ilo_mock_object.do_one_button_secure_erase.called) + self.assertEqual(states.CLEANWAIT, result) + mock_power.assert_called_once_with(task, states.REBOOT) + self.assertEqual(task.node.maintenance, True) + + @mock.patch.object(ilo_management.LOG, 'error', autospec=True) + @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) + @mock.patch.object(ilo_management.Ilo5Management, '_set_clean_failed', + autospec=True) + def test_one_button_secure_erase_ilo_error( + self, set_clean_failed_mock, ilo_mock, log_mock): + ilo_mock_object = ilo_mock.return_value + self.node.clean_step = {'step': 'one_button_secure_erase', + 'interface': 'management'} + self.node.save() + exc = ilo_error.IloError('error') + ilo_mock_object.do_one_button_secure_erase.side_effect = exc + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + task.driver.management.one_button_secure_erase(task) + set_clean_failed_mock.assert_called_once_with(mock.ANY, + task, exc) + self.assertTrue( + ilo_mock_object.do_one_button_secure_erase.called) + self.assertTrue(log_mock.called) diff --git a/releasenotes/notes/ilo5-oob-one-button-secure-erase-f55628f8aa767c20.yaml b/releasenotes/notes/ilo5-oob-one-button-secure-erase-f55628f8aa767c20.yaml new file mode 100644 index 0000000000..82c01759bb --- /dev/null +++ b/releasenotes/notes/ilo5-oob-one-button-secure-erase-f55628f8aa767c20.yaml @@ -0,0 +1,10 @@ +--- +features: + - Adds functionality to perform out-of-band one button secure erase + operation for iLO5 based HPE Proliant servers as a ``management`` + clean step ``one_button_secure_erase`` for ``ilo5`` hardware type. +upgrade: + - The ``do_one_button_secure_erase`` interface of 'proliantutils' library has + been enhanced to support out-of-band one button secure erase operation for + ``ilo5`` hardware type. To leverage this feature, the 'proliantutils' + library needs to be upgraded to version '2.10.0'.