Clean step to remove CA certificates from iLO

Implements clean step "clear_ca_certificates" to remove any 3rd party
expired/revoked CA certificates from iLO.

Change-Id: I0a3c1da9b94e4037a53ade100354ac51ca08db35
Story: #2008784
Task: #42175
This commit is contained in:
vinay50muddu 2021-07-05 10:09:35 +00:00 committed by Nisha Agarwal
parent 8434b56766
commit df4778605d
8 changed files with 316 additions and 12 deletions

View File

@ -56,6 +56,7 @@ The hardware type ``ilo`` supports following HPE server features:
* `Update Minimum Password Length security parameter as manual clean step`_ * `Update Minimum Password Length security parameter as manual clean step`_
* `Update Authentication Failure Logging security parameter as manual clean step`_ * `Update Authentication Failure Logging security parameter as manual clean step`_
* `Activating iLO Advanced license as manual clean step`_ * `Activating iLO Advanced license as manual clean step`_
* `Removing CA certificates from iLO as manual clean step`_
* `Firmware based UEFI iSCSI boot from volume support`_ * `Firmware based UEFI iSCSI boot from volume support`_
* `Certificate based validation in iLO`_ * `Certificate based validation in iLO`_
* `Rescue mode support`_ * `Rescue mode support`_
@ -702,6 +703,10 @@ Supported **Manual** Cleaning Operations
delivered with a flexible-quantity kit or after completing an Activation delivered with a flexible-quantity kit or after completing an Activation
Key Agreement (AKA), then the driver can still be used for executing Key Agreement (AKA), then the driver can still be used for executing
this cleaning step. this cleaning step.
``clear_ca_certificates``:
Removes the CA certificates from iLO. See
`Removing CA certificates from iLO as manual clean step`_ for user
guidance on usage.
``apply_configuration``: ``apply_configuration``:
Applies given BIOS settings on the node. See Applies given BIOS settings on the node. See
`BIOS configuration support`_. This step is part of the ``bios`` interface. `BIOS configuration support`_. This step is part of the ``bios`` interface.
@ -1477,6 +1482,37 @@ The different attributes of ``activate_license`` clean step are as follows:
"``args``", "Keyword-argument entry (<name>: <value>) being passed to clean step" "``args``", "Keyword-argument entry (<name>: <value>) being passed to clean step"
"``args.ilo_license_key``", "iLO Advanced license key to activate enterprise features. This is mandatory." "``args.ilo_license_key``", "iLO Advanced license key to activate enterprise features. This is mandatory."
Removing CA certificates from iLO as manual clean step
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
iLO driver can remove the invalidated CA certificates as a manual step.
Any manual cleaning step can only be initiated when a node is in the
``manageable`` state. Once the manual cleaning is finished, the node will be
put in the ``manageable`` state again. User can follow steps from
:ref:`manual_cleaning` to initiate manual cleaning operation on a node.
An example of a manual clean step with ``clear_ca_certificates`` as the only clean
step could be::
"clean_steps": [{
"interface": "management",
"step": "clear_ca_certificates",
"args": {
"certificate_files" : ["/path/to/certsA", "/path/to/certsB"]
}
}]
The different attributes of ``clear_ca_certificates`` clean step are as follows:
.. csv-table::
:header: "Attribute", "Description"
:widths: 30, 120
"``interface``", "Interface of clean step, here ``management``"
"``step``", "Name of clean step, here ``clear_ca_certificates``"
"``args``", "Keyword-argument entry (<name>: <value>) being passed to clean step"
"``args.certificate_files``", "List of CA certificates which are to be removed. "
"This is mandatory."
Initiating firmware update as manual clean step Initiating firmware update as manual clean step
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
iLO driver can invoke secure firmware update as a manual cleaning step. Any iLO driver can invoke secure firmware update as a manual cleaning step. Any

View File

@ -1022,11 +1022,16 @@ class IloUefiHttpsBoot(base.BootInterface):
iso_ref = image_utils.prepare_deploy_iso(task, ramdisk_params, iso_ref = image_utils.prepare_deploy_iso(task, ramdisk_params,
mode, d_info) mode, d_info)
# NOTE(vmud213): Do not call if it is in the middle of
# clear_ca_certificates clean step as the TLS pending settings will
# be overridden
if not node.driver_internal_info.get('clear_ca_certs_flag'):
ilo_common.add_certificates(task)
LOG.debug("Set 'UEFIHTTP' as one time boot option on the node " LOG.debug("Set 'UEFIHTTP' as one time boot option on the node "
"%(node)s to boot from URL %(iso_ref)s.", "%(node)s to boot from URL %(iso_ref)s.",
{'node': node.uuid, 'iso_ref': iso_ref}) {'node': node.uuid, 'iso_ref': iso_ref})
ilo_common.add_certificates(task)
ilo_common.setup_uefi_https(task, iso_ref) ilo_common.setup_uefi_https(task, iso_ref)
@METRICS.timer('IloUefiHttpsBoot.clean_up_ramdisk') @METRICS.timer('IloUefiHttpsBoot.clean_up_ramdisk')

View File

@ -1068,10 +1068,13 @@ def clear_certificates(task, cert_file_list=None):
node = task.node node = task.node
operation = (_("Clearing certificates from node %(node)s.") % operation = (_("Clearing certificates from node %(node)s.") %
{'node': node.uuid}) {'node': node.uuid})
# NOTE(vmud213): Exclude the certificates used to boot deploy images
exclude_cfl = _get_certificate_file_list(None)
try: try:
ilo_object = get_ilo_object(node) ilo_object = get_ilo_object(node)
ilo_object.remove_tls_certificate(cert_file_list) ilo_object.remove_tls_certificate(
cert_file_list=cert_file_list, excl_cert_file_list=exclude_cfl)
except ilo_error.IloCommandNotSupportedInBiosError as ilo_exception: except ilo_error.IloCommandNotSupportedInBiosError as ilo_exception:
raise exception.IloOperationNotSupported(operation=operation, raise exception.IloOperationNotSupported(operation=operation,
error=ilo_exception) error=ilo_exception)

View File

@ -186,6 +186,20 @@ _FIRMWARE_UPDATE_SUM_ARGSINFO = {
} }
} }
_CLEAR_CA_CERTS_ARGSINFO = {
'certificate_files': {
'description': (
"The list of files containing the certificates to be cleared. "
"If empty list is specified, all the certificates on the ilo "
"will be cleared, except the certificates in the file "
"configured with configuration parameter 'webserver_verify_ca' "
"are spared as they are required for booting the deploy image "
"for some boot interfaces."
),
'required': True
}
}
def _execute_ilo_step(node, step, *args, **kwargs): def _execute_ilo_step(node, step, *args, **kwargs):
"""Executes a particular deploy or clean step. """Executes a particular deploy or clean step.
@ -1128,3 +1142,51 @@ class Ilo5Management(IloManagement):
{'node': task.node.uuid, 'message': ilo_exception}) {'node': task.node.uuid, 'message': ilo_exception})
manager_utils.cleaning_error_handler(task, log_msg, manager_utils.cleaning_error_handler(task, log_msg,
errmsg=ilo_exception) errmsg=ilo_exception)
@base.clean_step(priority=0, argsinfo=_CLEAR_CA_CERTS_ARGSINFO)
def clear_ca_certificates(self, task, certificate_files):
"""Clears the certificates provided in the list of files to iLO.
:param task: a task from TaskManager.
:param certificate_files: a list of cerificate files.
:raises: NodeCleaningFailure, on failure to execute of clean step.
:raises: InstanceDeployFailure, on failure to execute of deploy step.
"""
node = task.node
driver_internal_info = node.driver_internal_info
if driver_internal_info.get('clear_ca_certs_flag'):
# NOTE(vmud213): Clear the flag and do nothing as this flow
# is part of the reboot required by the clean step that is
# already executed.
driver_internal_info.pop('clear_ca_certs_flag', None)
node.driver_internal_info = driver_internal_info
node.save()
return
try:
ilo_common.clear_certificates(task, certificate_files)
except (exception.IloOperationNotSupported,
exception.IloOperationError) as ir_exception:
msg = (_("Step 'clear_ca_certificates' failed on node %(node)s "
"with error: %(err)s") %
{'node': node.uuid, 'err': ir_exception})
if node.clean_step:
raise exception.NodeCleaningFailure(msg)
raise exception.InstanceDeployFailure(msg)
driver_internal_info['clear_ca_certs_flag'] = True
node.driver_internal_info = driver_internal_info
node.save()
deploy_opts = deploy_utils.build_agent_options(task.node)
task.driver.boot.prepare_ramdisk(task, deploy_opts)
manager_utils.node_power_action(task, states.REBOOT)
# set_async_step_flags calls node.save()
deploy_utils.set_async_step_flags(
node,
reboot=True,
skip_current_step=False)
return deploy_utils.get_async_step_return_state(task.node)

View File

@ -1812,7 +1812,11 @@ class IloUefiHttpsBootTestCase(db_base.DbTestCase):
task, ramdisk_params, mode, d_info) task, ramdisk_params, mode, d_info)
setup_uefi_https_mock.assert_called_once_with(task, setup_uefi_https_mock.assert_called_once_with(task,
'recreated-iso') 'recreated-iso')
add_mock.assert_called_once_with(task) if task.node.driver_internal_info.get("clear_ca_certs_flag",
False):
add_mock.assert_not_called()
else:
add_mock.assert_called_once_with(task)
def test_prepare_ramdisk_rescue_glance_image(self): def test_prepare_ramdisk_rescue_glance_image(self):
self._test_prepare_ramdisk( self._test_prepare_ramdisk(
@ -1832,6 +1836,21 @@ class IloUefiHttpsBootTestCase(db_base.DbTestCase):
self.node.instance_info['boot_iso']) self.node.instance_info['boot_iso'])
def test_prepare_ramdisk_glance_image(self): def test_prepare_ramdisk_glance_image(self):
driver_internal_info = self.node.driver_internal_info
driver_internal_info['clear_ca_certs_flag'] = False
self.node.driver_internal_info = driver_internal_info
self.node.save()
self._test_prepare_ramdisk(
ilo_boot_iso='swift:abcdef',
image_source='6b2f0c0c-79e8-4db6-842e-43c9764204af')
self.node.refresh()
self.assertNotIn('boot_iso', self.node.instance_info)
def test_prepare_ramdisk_middle_of_clean_step(self):
driver_internal_info = self.node.driver_internal_info
driver_internal_info['clear_ca_certs_flag'] = True
self.node.driver_internal_info = driver_internal_info
self.node.save()
self._test_prepare_ramdisk( self._test_prepare_ramdisk(
ilo_boot_iso='swift:abcdef', ilo_boot_iso='swift:abcdef',
image_source='6b2f0c0c-79e8-4db6-842e-43c9764204af') image_source='6b2f0c0c-79e8-4db6-842e-43c9764204af')

View File

@ -1370,34 +1370,50 @@ class IloCommonMethodsTestCase(BaseIloTest):
get_cl_mock.assert_called_once_with(c_l) get_cl_mock.assert_called_once_with(c_l)
ilo_mock_object.add_tls_certificate.assert_called_once_with(c_l) ilo_mock_object.add_tls_certificate.assert_called_once_with(c_l)
@mock.patch.object(ilo_common, '_get_certificate_file_list',
spec_set=True, autospec=True)
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
autospec=True) autospec=True)
def test_clear_certificates(self, get_ilo_object_mock): def test_clear_certificates(self, get_ilo_object_mock,
get_certs_mock):
ilo_mock_object = get_ilo_object_mock.return_value ilo_mock_object = get_ilo_object_mock.return_value
c_l = ['/file/path/a', '/file/path/b'] c_l = ['/file/path/a', '/file/path/b']
get_certs_mock.return_value = ['/file/path/x']
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task: shared=False) as task:
ilo_common.clear_certificates(task, c_l) ilo_common.clear_certificates(task, c_l)
ilo_mock_object.remove_tls_certificate.assert_called_once_with(c_l) ilo_mock_object.remove_tls_certificate.assert_called_once_with(
cert_file_list=c_l, excl_cert_file_list=['/file/path/x'])
get_certs_mock.assert_called_once_with(None)
@mock.patch.object(ilo_common, '_get_certificate_file_list',
spec_set=True, autospec=True)
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
autospec=True) autospec=True)
def test_clear_certificates_default(self, get_ilo_object_mock): def test_clear_certificates_default(self, get_ilo_object_mock,
get_certs_mock):
ilo_mock_object = get_ilo_object_mock.return_value ilo_mock_object = get_ilo_object_mock.return_value
get_certs_mock.return_value = ['/file/path/x']
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task: shared=False) as task:
ilo_common.clear_certificates(task) ilo_common.clear_certificates(task)
ilo_mock_object.remove_tls_certificate.assert_called_once_with(None) ilo_mock_object.remove_tls_certificate.assert_called_once_with(
cert_file_list=None, excl_cert_file_list=['/file/path/x'])
get_certs_mock.assert_called_once_with(None)
@mock.patch.object(ilo_common, '_get_certificate_file_list',
spec_set=True, autospec=True)
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
autospec=True) autospec=True)
def test_clear_certificates_raises_ilo_error(self, get_ilo_object_mock): def test_clear_certificates_raises_ilo_error(self, get_ilo_object_mock,
get_certs_mock):
ilo_mock_object = get_ilo_object_mock.return_value ilo_mock_object = get_ilo_object_mock.return_value
c_l = ['/file/path/a', '/file/path/b'] c_l = ['/file/path/a', '/file/path/b']
get_certs_mock.return_value = ['/file/path/x']
exc = ilo_error.IloError('error') exc = ilo_error.IloError('error')
ilo_mock_object.remove_tls_certificate.side_effect = exc ilo_mock_object.remove_tls_certificate.side_effect = exc
@ -1407,7 +1423,9 @@ class IloCommonMethodsTestCase(BaseIloTest):
ilo_common.clear_certificates, ilo_common.clear_certificates,
task, c_l) task, c_l)
ilo_mock_object.remove_tls_certificate.assert_called_once_with(c_l) ilo_mock_object.remove_tls_certificate.assert_called_once_with(
cert_file_list=c_l, excl_cert_file_list=['/file/path/x'])
get_certs_mock.assert_called_once_with(None)
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
autospec=True) autospec=True)

View File

@ -1525,12 +1525,10 @@ class Ilo5ManagementTestCase(db_base.DbTestCase):
def setUp(self): def setUp(self):
super(Ilo5ManagementTestCase, self).setUp() super(Ilo5ManagementTestCase, self).setUp()
self.driver = mock.Mock(management=ilo_management.Ilo5Management()) self.driver = mock.Mock(management=ilo_management.Ilo5Management())
self.clean_step = {'step': 'erase_devices',
'interface': 'management'}
n = { n = {
'driver': 'ilo5', 'driver': 'ilo5',
'driver_info': INFO_DICT, 'driver_info': INFO_DICT,
'clean_step': self.clean_step,
} }
self.config(enabled_hardware_types=['ilo5'], self.config(enabled_hardware_types=['ilo5'],
enabled_boot_interfaces=['ilo-virtual-media'], enabled_boot_interfaces=['ilo-virtual-media'],
@ -1547,6 +1545,9 @@ class Ilo5ManagementTestCase(db_base.DbTestCase):
@mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True)
@mock.patch.object(manager_utils, 'node_power_action', autospec=True) @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
def test_erase_devices_hdd(self, mock_power, ilo_mock, build_agent_mock): def test_erase_devices_hdd(self, mock_power, ilo_mock, build_agent_mock):
self.node.clean_step = {'interface': 'management',
'step': 'erase_devices'}
self.node.save()
ilo_mock_object = ilo_mock.return_value ilo_mock_object = ilo_mock.return_value
ilo_mock_object.get_available_disk_types.return_value = ['HDD'] ilo_mock_object.get_available_disk_types.return_value = ['HDD']
build_agent_mock.return_value = [] build_agent_mock.return_value = []
@ -1572,6 +1573,9 @@ class Ilo5ManagementTestCase(db_base.DbTestCase):
@mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True)
@mock.patch.object(manager_utils, 'node_power_action', autospec=True) @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
def test_erase_devices_ssd(self, mock_power, ilo_mock, build_agent_mock): def test_erase_devices_ssd(self, mock_power, ilo_mock, build_agent_mock):
self.node.clean_step = {'interface': 'management',
'step': 'erase_devices'}
self.node.save()
ilo_mock_object = ilo_mock.return_value ilo_mock_object = ilo_mock.return_value
ilo_mock_object.get_available_disk_types.return_value = ['SSD'] ilo_mock_object.get_available_disk_types.return_value = ['SSD']
build_agent_mock.return_value = [] build_agent_mock.return_value = []
@ -1601,6 +1605,9 @@ class Ilo5ManagementTestCase(db_base.DbTestCase):
@mock.patch.object(manager_utils, 'node_power_action', autospec=True) @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
def test_erase_devices_ssd_when_hdd_done(self, mock_power, ilo_mock, def test_erase_devices_ssd_when_hdd_done(self, mock_power, ilo_mock,
build_agent_mock): build_agent_mock):
self.node.clean_step = {'interface': 'management',
'step': 'erase_devices'}
self.node.save()
build_agent_mock.return_value = [] build_agent_mock.return_value = []
ilo_mock_object = ilo_mock.return_value ilo_mock_object = ilo_mock.return_value
ilo_mock_object.get_available_disk_types.return_value = ['HDD', 'SSD'] ilo_mock_object.get_available_disk_types.return_value = ['HDD', 'SSD']
@ -1632,6 +1639,9 @@ class Ilo5ManagementTestCase(db_base.DbTestCase):
@mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True)
def test_erase_devices_completed(self, ilo_mock, disk_status_mock, def test_erase_devices_completed(self, ilo_mock, disk_status_mock,
log_mock): log_mock):
self.node.clean_step = {'interface': 'management',
'step': 'erase_devices'}
self.node.save()
ilo_mock_object = ilo_mock.return_value ilo_mock_object = ilo_mock.return_value
ilo_mock_object.get_available_disk_types.return_value = ['HDD', 'SSD'] ilo_mock_object.get_available_disk_types.return_value = ['HDD', 'SSD']
disk_status_mock.return_value = True disk_status_mock.return_value = True
@ -1655,6 +1665,9 @@ class Ilo5ManagementTestCase(db_base.DbTestCase):
@mock.patch.object(manager_utils, 'node_power_action', autospec=True) @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
def test_erase_devices_hdd_with_erase_pattern_zero( def test_erase_devices_hdd_with_erase_pattern_zero(
self, mock_power, ilo_mock, build_agent_mock): self, mock_power, ilo_mock, build_agent_mock):
self.node.clean_step = {'interface': 'management',
'step': 'erase_devices'}
self.node.save()
ilo_mock_object = ilo_mock.return_value ilo_mock_object = ilo_mock.return_value
ilo_mock_object.get_available_disk_types.return_value = ['HDD'] ilo_mock_object.get_available_disk_types.return_value = ['HDD']
build_agent_mock.return_value = [] build_agent_mock.return_value = []
@ -1680,6 +1693,9 @@ class Ilo5ManagementTestCase(db_base.DbTestCase):
@mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True)
def test_erase_devices_when_no_drive_available( def test_erase_devices_when_no_drive_available(
self, ilo_mock, log_mock): self, ilo_mock, log_mock):
self.node.clean_step = {'interface': 'management',
'step': 'erase_devices'}
self.node.save()
ilo_mock_object = ilo_mock.return_value ilo_mock_object = ilo_mock.return_value
ilo_mock_object.get_available_disk_types.return_value = [] ilo_mock_object.get_available_disk_types.return_value = []
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
@ -1689,6 +1705,9 @@ class Ilo5ManagementTestCase(db_base.DbTestCase):
def test_erase_devices_hdd_with_invalid_format_erase_pattern( def test_erase_devices_hdd_with_invalid_format_erase_pattern(
self): self):
self.node.clean_step = {'interface': 'management',
'step': 'erase_devices'}
self.node.save()
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task: shared=False) as task:
self.assertRaises(exception.InvalidParameterValue, self.assertRaises(exception.InvalidParameterValue,
@ -1697,6 +1716,9 @@ class Ilo5ManagementTestCase(db_base.DbTestCase):
def test_erase_devices_hdd_with_invalid_device_type_erase_pattern( def test_erase_devices_hdd_with_invalid_device_type_erase_pattern(
self): self):
self.node.clean_step = {'interface': 'management',
'step': 'erase_devices'}
self.node.save()
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task: shared=False) as task:
self.assertRaises(exception.InvalidParameterValue, self.assertRaises(exception.InvalidParameterValue,
@ -1705,6 +1727,9 @@ class Ilo5ManagementTestCase(db_base.DbTestCase):
def test_erase_devices_hdd_with_invalid_erase_pattern( def test_erase_devices_hdd_with_invalid_erase_pattern(
self): self):
self.node.clean_step = {'interface': 'management',
'step': 'erase_devices'}
self.node.save()
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task: shared=False) as task:
self.assertRaises(exception.InvalidParameterValue, self.assertRaises(exception.InvalidParameterValue,
@ -1716,6 +1741,9 @@ class Ilo5ManagementTestCase(db_base.DbTestCase):
autospec=True) autospec=True)
def test_erase_devices_hdd_ilo_error(self, clean_err_handler_mock, def test_erase_devices_hdd_ilo_error(self, clean_err_handler_mock,
ilo_mock): ilo_mock):
self.node.clean_step = {'interface': 'management',
'step': 'erase_devices'}
self.node.save()
ilo_mock_object = ilo_mock.return_value ilo_mock_object = ilo_mock.return_value
ilo_mock_object.get_available_disk_types.return_value = ['HDD'] ilo_mock_object.get_available_disk_types.return_value = ['HDD']
exc = ilo_error.IloError('error') exc = ilo_error.IloError('error')
@ -1776,3 +1804,131 @@ class Ilo5ManagementTestCase(db_base.DbTestCase):
errmsg=exc) errmsg=exc)
self.assertTrue( self.assertTrue(
ilo_mock_object.do_one_button_secure_erase.called) ilo_mock_object.do_one_button_secure_erase.called)
@mock.patch.object(deploy_utils, 'get_async_step_return_state',
spec_set=True, autospec=True)
@mock.patch.object(deploy_utils, 'set_async_step_flags',
spec_set=True, autospec=True)
@mock.patch.object(deploy_utils, 'build_agent_options',
spec_set=True, autospec=True)
@mock.patch.object(manager_utils, 'node_power_action', autospec=True)
@mock.patch.object(ilo_boot.IloVirtualMediaBoot, 'prepare_ramdisk',
spec_set=True, autospec=True)
@mock.patch.object(ilo_common, 'clear_certificates', spec_set=True,
autospec=True)
def test_clear_ca_certificates(self, clear_certs_mock,
prepare_ramdisk_mock, node_power_mock,
build_agent_mock, set_async_mock,
get_async_ret_mock):
self.node.clean_step = {'interface': 'management',
'step': 'clear_ca_certificates'}
self.node.save()
build_agent_mock.return_value = {'a': 'x', 'b': 'y'}
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
certificate_files = ["/path/to/certsA", "/path/to/certsB"]
task.driver.management.clear_ca_certificates(
task, certificate_files)
clear_certs_mock.assert_called_once_with(
task, certificate_files)
self.assertTrue(task.node.driver_internal_info.get(
'clear_ca_certs_flag'))
build_agent_mock.assert_called_once_with(task.node)
prepare_ramdisk_mock.assert_called_once_with(
mock.ANY, task, {'a': 'x', 'b': 'y'})
node_power_mock.assert_called_once_with(task, states.REBOOT)
set_async_mock.assert_called_once_with(
task.node, reboot=True, skip_current_step=False)
get_async_ret_mock.assert_called_once_with(task.node)
@mock.patch.object(deploy_utils, 'get_async_step_return_state',
spec_set=True, autospec=True)
@mock.patch.object(deploy_utils, 'set_async_step_flags',
spec_set=True, autospec=True)
@mock.patch.object(deploy_utils, 'build_agent_options',
spec_set=True, autospec=True)
@mock.patch.object(manager_utils, 'node_power_action', autospec=True)
@mock.patch.object(ilo_boot.IloVirtualMediaBoot, 'prepare_ramdisk',
spec_set=True, autospec=True)
@mock.patch.object(ilo_common, 'clear_certificates', spec_set=True,
autospec=True)
def test_clear_ca_certificates_clear_flag(
self, clear_certs_mock, prepare_ramdisk_mock, node_power_mock,
build_agent_mock, set_async_mock, get_async_ret_mock):
self.node.clean_step = {'interface': 'management',
'step': 'clear_ca_certificates'}
self.node.save()
build_agent_mock.return_value = {'a': 'x', 'b': 'y'}
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
certificate_files = ["/path/to/certsA", "/path/to/certsB"]
driver_internal_info = task.node.driver_internal_info
driver_internal_info['clear_ca_certs_flag'] = True
task.node.driver_internal_info = driver_internal_info
task.driver.management.clear_ca_certificates(
task, certificate_files)
clear_certs_mock.assert_not_called()
build_agent_mock.assert_not_called()
prepare_ramdisk_mock.assert_not_called()
node_power_mock.assert_not_called()
set_async_mock.assert_not_called()
get_async_ret_mock.assert_not_called()
@mock.patch.object(deploy_utils, 'get_async_step_return_state',
spec_set=True, autospec=True)
@mock.patch.object(deploy_utils, 'set_async_step_flags',
spec_set=True, autospec=True)
@mock.patch.object(deploy_utils, 'build_agent_options',
spec_set=True, autospec=True)
@mock.patch.object(manager_utils, 'node_power_action', autospec=True)
@mock.patch.object(ilo_boot.IloVirtualMediaBoot, 'prepare_ramdisk',
spec_set=True, autospec=True)
@mock.patch.object(ilo_common, 'clear_certificates', spec_set=True,
autospec=True)
def test_clear_ca_certificates_ilo_operation_not_supported(
self, clear_certs_mock, prepare_ramdisk_mock, node_power_mock,
build_agent_mock, set_async_mock, get_async_ret_mock):
self.node.clean_step = {'interface': 'management',
'step': 'clear_ca_certificates'}
self.node.save()
exc = exception.IloOperationNotSupported('error')
clear_certs_mock.side_effect = exc
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
certificate_files = ["/path/to/certsA", "/path/to/certsB"]
self.assertRaises(exception.NodeCleaningFailure,
task.driver.management.clear_ca_certificates,
task, certificate_files)
build_agent_mock.assert_not_called()
prepare_ramdisk_mock.assert_not_called()
node_power_mock.assert_not_called()
set_async_mock.assert_not_called()
get_async_ret_mock.assert_not_called()
@mock.patch.object(ilo_common, 'clear_certificates', spec_set=True,
autospec=True)
def test_clear_ca_certificates_ilo_operation_error(self, clear_certs_mock):
self.node.deploy_step = {'interface': 'management',
'step': 'clear_ca_certificates'}
self.node.save()
exc = exception.IloOperationError('error')
clear_certs_mock.side_effect = exc
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
certificate_files = ["/path/to/certsA", "/path/to/certsB"]
self.assertRaises(exception.InstanceDeployFailure,
task.driver.management.clear_ca_certificates,
task, certificate_files)

View File

@ -0,0 +1,5 @@
---
features:
- |
Manual clean step ``clear_ca_certificates`` is added to remove the
CA certificates from iLO.