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:
parent
8434b56766
commit
df4778605d
@ -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
|
||||||
|
@ -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')
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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')
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
5
releasenotes/notes/clear_ca_cert-db41e7be9723c0fb.yaml
Normal file
5
releasenotes/notes/clear_ca_cert-db41e7be9723c0fb.yaml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Manual clean step ``clear_ca_certificates`` is added to remove the
|
||||||
|
CA certificates from iLO.
|
Loading…
Reference in New Issue
Block a user