Merge "Secure boot support for pxe_ilo driver"

This commit is contained in:
Jenkins 2015-08-04 10:15:46 +00:00 committed by Gerrit Code Review
commit d4aa1428ae
2 changed files with 142 additions and 29 deletions

View File

@ -368,6 +368,24 @@ def _update_secure_boot_mode(task, mode):
{'mode': mode, 'node': task.node.uuid})
def _disable_secure_boot_if_supported(task):
"""Disables secure boot on node, does not throw if its not supported.
:param task: a TaskManager instance containing the node to act on.
:raises: IloOperationError, if some operation on iLO failed.
"""
try:
_update_secure_boot_mode(task, False)
# We need to handle IloOperationNotSupported exception so that if
# the user has incorrectly specified the Node capability
# 'secure_boot' to a node that does not have that capability and
# attempted deploy. Handling this exception here, will help the
# user to tear down such a Node.
except exception.IloOperationNotSupported:
LOG.warn(_LW('Secure boot mode is not supported for node %s'),
task.node.uuid)
class IloVirtualMediaIscsiDeploy(base.DeployInterface):
def get_properties(self):
@ -453,16 +471,7 @@ class IloVirtualMediaIscsiDeploy(base.DeployInterface):
:returns: deploy state DELETED.
"""
manager_utils.node_power_action(task, states.POWER_OFF)
try:
_update_secure_boot_mode(task, False)
# We need to handle IloOperationNotSupported exception so that if
# the user has incorrectly specified the Node capability
# 'secure_boot' to a node that does not have that capability and
# attempted deploy. Handling this exception here, will help the
# user to tear down such a Node.
except exception.IloOperationNotSupported:
LOG.warn(_LW('Secure boot mode is not supported for node %s'),
task.node.uuid)
_disable_secure_boot_if_supported(task)
return states.DELETED
def prepare(self, task):
@ -532,16 +541,7 @@ class IloVirtualMediaAgentDeploy(base.DeployInterface):
:returns: states.DELETED
"""
manager_utils.node_power_action(task, states.POWER_OFF)
try:
_update_secure_boot_mode(task, False)
# We need to handle IloOperationNotSupported exception so that if
# User had incorrectly specified the Node capability 'secure_boot'
# to a node that do not have such capability and attempted deploy.
# Handling this exception here, will help user to tear down such a
# Node.
except exception.IloOperationNotSupported:
LOG.warn(_LW('Secure boot mode is not supported for node %s'),
task.node.uuid)
_disable_secure_boot_if_supported(task)
return states.DELETED
def prepare(self, task):
@ -661,7 +661,7 @@ class IloPXEDeploy(iscsi_deploy.ISCSIDeploy):
:raises: IloOperationError, if some operation on iLO failed.
:raises: InvalidParameterValue, if some information is invalid.
"""
ilo_common.update_boot_mode(task)
_prepare_node_for_deploy(task)
# Check if 'boot_option' is compatible with 'boot_mode' and image.
# Whole disk image deploy is not supported in UEFI boot mode if
@ -687,6 +687,19 @@ class IloPXEDeploy(iscsi_deploy.ISCSIDeploy):
manager_utils.node_set_boot_device(task, boot_devices.PXE)
return super(IloPXEDeploy, self).deploy(task)
@task_manager.require_exclusive_lock
def tear_down(self, task):
"""Tear down a previous deployment on the task's node.
:param task: a TaskManager instance.
:returns: states.DELETED
"""
# Powering off the Node before disabling secure boot. If the node is
# is in POST, disable secure boot will fail.
manager_utils.node_power_action(task, states.POWER_OFF)
_disable_secure_boot_if_supported(task)
return super(IloPXEDeploy, self).tear_down(task)
class IloConsoleInterface(ipmitool.IPMIShellinaboxConsole):
"""A ConsoleInterface that uses ipmitool and shellinabox."""
@ -718,9 +731,40 @@ class IloPXEVendorPassthru(iscsi_deploy.VendorPassthru):
@base.passthru(['POST'])
def pass_deploy_info(self, task, **kwargs):
manager_utils.node_set_boot_device(task, boot_devices.PXE, True)
LOG.debug('Pass deploy info for the deployment on node %s',
task.node.uuid)
manager_utils.node_set_boot_device(task, boot_devices.PXE,
persistent=True)
# Set boot mode
ilo_common.update_boot_mode(task)
# Need to enable secure boot, if being requested
_update_secure_boot_mode(task, True)
super(IloPXEVendorPassthru, self).pass_deploy_info(task, **kwargs)
@task_manager.require_exclusive_lock
def continue_deploy(self, task, **kwargs):
"""Method invoked when deployed with the IPA ramdisk.
This method is invoked during a heartbeat from an agent when
the node is in wait-call-back state. This deploys the image on
the node and then configures the node to boot according to the
desired boot option (netboot or localboot).
:param task: a TaskManager object containing the node.
:param kwargs: the kwargs passed from the heartbeat method.
:raises: InstanceDeployFailure, if it encounters some error during
the deploy.
:raises: IloOperationError, if some operation on iLO failed.
"""
LOG.debug('Continuing the deployment on node %s', task.node.uuid)
# Set boot mode
ilo_common.update_boot_mode(task)
# Need to enable secure boot, if being requested
_update_secure_boot_mode(task, True)
super(IloPXEVendorPassthru, self).continue_deploy(task, **kwargs)
class VendorPassthru(agent_base_vendor.BaseAgentVendor):
"""Vendor-specific interfaces for iLO deploy drivers."""

View File

@ -1395,24 +1395,24 @@ class IloPXEDeployTestCase(db_base.DbTestCase):
@mock.patch.object(iscsi_deploy.ISCSIDeploy, 'prepare', spec_set=True,
autospec=True)
@mock.patch.object(ilo_common, 'update_boot_mode', spec_set=True,
@mock.patch.object(ilo_deploy, '_prepare_node_for_deploy', spec_set=True,
autospec=True)
def test_prepare(self,
update_boot_mode_mock,
prepare_node_mock,
pxe_prepare_mock):
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
task.node.properties['capabilities'] = 'boot_mode:uefi'
task.driver.deploy.prepare(task)
update_boot_mode_mock.assert_called_once_with(task)
prepare_node_mock.assert_called_once_with(task)
pxe_prepare_mock.assert_called_once_with(mock.ANY, task)
@mock.patch.object(iscsi_deploy.ISCSIDeploy, 'prepare', spec_set=True,
autospec=True)
@mock.patch.object(ilo_common, 'update_boot_mode', spec_set=True,
@mock.patch.object(ilo_deploy, '_prepare_node_for_deploy', spec_set=True,
autospec=True)
def test_prepare_uefi_whole_disk_image_fail(self,
update_boot_mode_mock,
prepare_node_for_deploy_mock,
pxe_prepare_mock):
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
@ -1420,7 +1420,7 @@ class IloPXEDeployTestCase(db_base.DbTestCase):
task.node.driver_internal_info['is_whole_disk_image'] = True
self.assertRaises(exception.InvalidParameterValue,
task.driver.deploy.prepare, task)
update_boot_mode_mock.assert_called_once_with(task)
prepare_node_for_deploy_mock.assert_called_once_with(task)
self.assertFalse(pxe_prepare_mock.called)
@mock.patch.object(iscsi_deploy.ISCSIDeploy, 'deploy', spec_set=True,
@ -1435,6 +1435,48 @@ class IloPXEDeployTestCase(db_base.DbTestCase):
set_persistent_mock.assert_called_with(task, boot_devices.PXE)
pxe_deploy_mock.assert_called_once_with(mock.ANY, task)
@mock.patch.object(iscsi_deploy.ISCSIDeploy, 'tear_down',
spec_set=True, autospec=True)
@mock.patch.object(ilo_deploy, '_update_secure_boot_mode', autospec=True)
@mock.patch.object(manager_utils, 'node_power_action', spec_set=True,
autospec=True)
def test_tear_down(self, node_power_action_mock,
update_secure_boot_mode_mock, pxe_tear_down_mock):
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
pxe_tear_down_mock.return_value = states.DELETED
returned_state = task.driver.deploy.tear_down(task)
node_power_action_mock.assert_called_once_with(task,
states.POWER_OFF)
update_secure_boot_mode_mock.assert_called_once_with(task, False)
pxe_tear_down_mock.assert_called_once_with(mock.ANY, task)
self.assertEqual(states.DELETED, returned_state)
@mock.patch.object(ilo_deploy.LOG, 'warn', spec_set=True, autospec=True)
@mock.patch.object(iscsi_deploy.ISCSIDeploy, 'tear_down',
spec_set=True, autospec=True)
@mock.patch.object(ilo_deploy, 'exception', spec_set=True, autospec=True)
@mock.patch.object(ilo_deploy, '_update_secure_boot_mode',
spec_set=True, autospec=True)
@mock.patch.object(manager_utils, 'node_power_action', spec_set=True,
autospec=True)
def test_tear_down_handle_exception(self, node_power_action_mock,
update_secure_boot_mode_mock,
exception_mock, pxe_tear_down_mock,
mock_log):
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
pxe_tear_down_mock.return_value = states.DELETED
exception_mock.IloOperationNotSupported = Exception
update_secure_boot_mode_mock.side_effect = Exception
returned_state = task.driver.deploy.tear_down(task)
update_secure_boot_mode_mock.assert_called_once_with(task, False)
pxe_tear_down_mock.assert_called_once_with(mock.ANY, task)
node_power_action_mock.assert_called_once_with(task,
states.POWER_OFF)
self.assertTrue(mock_log.called)
self.assertEqual(states.DELETED, returned_state)
class IloPXEVendorPassthruTestCase(db_base.DbTestCase):
@ -1463,9 +1505,15 @@ class IloPXEVendorPassthruTestCase(db_base.DbTestCase):
@mock.patch.object(iscsi_deploy.VendorPassthru, 'pass_deploy_info',
spec_set=True, autospec=True)
@mock.patch.object(ilo_deploy, '_update_secure_boot_mode', spec_set=True,
autospec=True)
@mock.patch.object(ilo_common, 'update_boot_mode', spec_set=True,
autospec=True)
@mock.patch.object(manager_utils, 'node_set_boot_device', spec_set=True,
autospec=True)
def test_vendorpassthru_pass_deploy_info(self, set_boot_device_mock,
func_update_boot_mode,
func_update_secure_boot_mode,
pxe_vendorpassthru_mock):
kwargs = {'address': '123456'}
with task_manager.acquire(self.context, self.node.uuid,
@ -1474,7 +1522,28 @@ class IloPXEVendorPassthruTestCase(db_base.DbTestCase):
task.node.target_provision_state = states.ACTIVE
task.driver.vendor.pass_deploy_info(task, **kwargs)
set_boot_device_mock.assert_called_with(task, boot_devices.PXE,
True)
persistent=True)
func_update_boot_mode.assert_called_once_with(task)
func_update_secure_boot_mode.assert_called_once_with(task, True)
pxe_vendorpassthru_mock.assert_called_once_with(
mock.ANY, task, **kwargs)
@mock.patch.object(iscsi_deploy.VendorPassthru, 'continue_deploy',
spec_set=True, autospec=True)
@mock.patch.object(ilo_deploy, '_update_secure_boot_mode', autospec=True)
@mock.patch.object(ilo_common, 'update_boot_mode', autospec=True)
def test_vendorpassthru_continue_deploy(self,
func_update_boot_mode,
func_update_secure_boot_mode,
pxe_vendorpassthru_mock):
kwargs = {'address': '123456'}
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
task.node.provision_state = states.DEPLOYWAIT
task.node.target_provision_state = states.ACTIVE
task.driver.vendor.continue_deploy(task, **kwargs)
func_update_boot_mode.assert_called_once_with(task)
func_update_secure_boot_mode.assert_called_once_with(task, True)
pxe_vendorpassthru_mock.assert_called_once_with(
mock.ANY, task, **kwargs)