Adds boot mode support to iLO management interface
This change adds 'get_boot_mode', 'set_boot_mode' and 'get_supported_boot_modes' methods to driver management interface of 'ilo' and 'ilo5' hardware types. Story: 2007827 Task: 40104 Change-Id: I34701b790ba91431b0b943ae8060a43d7ea9abbb
This commit is contained in:
parent
1c0a9c8c28
commit
e43aee3db8
@ -116,6 +116,15 @@ POST_INPOSTDISCOVERY_STATE = "InPostDiscoveryComplete"
|
||||
POST_FINISHEDPOST_STATE = "FinishedPost"
|
||||
""" Node is in FinishedPost post state."""
|
||||
|
||||
SUPPORTED_BOOT_MODE_LEGACY_BIOS_ONLY = 'legacy bios only'
|
||||
""" Node supports only legacy BIOS boot mode."""
|
||||
|
||||
SUPPORTED_BOOT_MODE_UEFI_ONLY = 'uefi only'
|
||||
""" Node supports only UEFI boot mode."""
|
||||
|
||||
SUPPORTED_BOOT_MODE_LEGACY_BIOS_AND_UEFI = 'legacy bios and uefi'
|
||||
""" Node supports both legacy BIOS and UEFI boot mode."""
|
||||
|
||||
|
||||
def copy_image_to_web_server(source_file_path, destination):
|
||||
"""Copies the given image to the http web server.
|
||||
@ -492,6 +501,24 @@ def set_boot_mode(node, boot_mode):
|
||||
{'uuid': node.uuid, 'boot_mode': boot_mode})
|
||||
|
||||
|
||||
def get_current_boot_mode(node):
|
||||
"""Get the current boot mode for a node.
|
||||
|
||||
:param node: an ironic node object.
|
||||
:raises: IloOperationError if failed to fetch boot mode.
|
||||
:raises: IloOperationNotSupported if node does not support getting pending
|
||||
boot mode.
|
||||
"""
|
||||
ilo_object = get_ilo_object(node)
|
||||
operation = _("Get current boot mode")
|
||||
try:
|
||||
c_boot_mode = ilo_object.get_current_boot_mode()
|
||||
return BOOT_MODE_ILO_TO_GENERIC[c_boot_mode.lower()]
|
||||
except ilo_error.IloError as ilo_exception:
|
||||
raise exception.IloOperationError(operation=operation,
|
||||
error=ilo_exception)
|
||||
|
||||
|
||||
def update_boot_mode(task):
|
||||
"""Update instance_info with boot mode to be used for deploy.
|
||||
|
||||
|
@ -24,6 +24,7 @@ from oslo_utils import excutils
|
||||
from oslo_utils import importutils
|
||||
|
||||
from ironic.common import boot_devices
|
||||
from ironic.common import boot_modes
|
||||
from ironic.common import exception
|
||||
from ironic.common.i18n import _
|
||||
from ironic.common import states
|
||||
@ -684,6 +685,59 @@ class IloManagement(base.ManagementInterface):
|
||||
raise exception.IloOperationError(operation=operation,
|
||||
error=ilo_exception)
|
||||
|
||||
def get_supported_boot_modes(self, task):
|
||||
"""Get a list of the supported boot devices.
|
||||
|
||||
:param task: a task from TaskManager.
|
||||
:raises: IloOperationError if any exception happens in proliantutils
|
||||
:returns: A list with the supported boot devices defined
|
||||
in :mod:`ironic.common.boot_devices`.
|
||||
"""
|
||||
node = task.node
|
||||
ilo_object = ilo_common.get_ilo_object(node)
|
||||
try:
|
||||
modes = ilo_object.get_supported_boot_mode()
|
||||
if modes == ilo_common.SUPPORTED_BOOT_MODE_LEGACY_BIOS_ONLY:
|
||||
return [boot_modes.LEGACY_BIOS]
|
||||
elif modes == ilo_common.SUPPORTED_BOOT_MODE_UEFI_ONLY:
|
||||
return [boot_modes.UEFI]
|
||||
elif modes == ilo_common.SUPPORTED_BOOT_MODE_LEGACY_BIOS_AND_UEFI:
|
||||
return [boot_modes.UEFI, boot_modes.LEGACY_BIOS]
|
||||
except ilo_error.IloError as ilo_exception:
|
||||
operation = _("Get supported boot modes")
|
||||
raise exception.IloOperationError(operation=operation,
|
||||
error=ilo_exception)
|
||||
|
||||
@task_manager.require_exclusive_lock
|
||||
def set_boot_mode(self, task, mode):
|
||||
"""Set the boot mode for a node.
|
||||
|
||||
Set the boot mode to use on next reboot of the node.
|
||||
|
||||
:param task: A task from TaskManager.
|
||||
:param mode: The boot mode, one of
|
||||
:mod:`ironic.common.boot_modes`.
|
||||
:raises: InvalidParameterValue if an invalid boot mode is
|
||||
specified.
|
||||
:raises: IloOperationError if setting boot mode failed.
|
||||
"""
|
||||
if mode not in self.get_supported_boot_modes(task):
|
||||
raise exception.InvalidParameterValue(_(
|
||||
"The given boot mode '%s' is not supported.") % mode)
|
||||
ilo_common.set_boot_mode(task.node, mode)
|
||||
|
||||
def get_boot_mode(self, task):
|
||||
"""Get the current boot mode for a node.
|
||||
|
||||
Provides the current boot mode of the node.
|
||||
|
||||
:param task: A task from TaskManager.
|
||||
:raises: IloOperationError on an error from IloClient library.
|
||||
:returns: The boot mode, one of :mod:`ironic.common.boot_mode` or
|
||||
None if it is unknown.
|
||||
"""
|
||||
return ilo_common.get_current_boot_mode(task.node)
|
||||
|
||||
|
||||
class Ilo5Management(IloManagement):
|
||||
|
||||
|
@ -436,6 +436,29 @@ class IloCommonMethodsTestCase(BaseIloTest):
|
||||
get_ilo_object_mock.assert_called_once_with(self.node)
|
||||
get_pending_boot_mode_mock.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_get_current_boot_mode(self, get_ilo_object_mock):
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
get_current_boot_mode_mock = ilo_object_mock.get_current_boot_mode
|
||||
get_current_boot_mode_mock.return_value = 'LEGACY'
|
||||
ret = ilo_common.get_current_boot_mode(self.node)
|
||||
self.assertEqual('bios', ret)
|
||||
get_ilo_object_mock.assert_called_once_with(self.node)
|
||||
get_current_boot_mode_mock.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_get_current_boot_mode_fail(self, get_ilo_object_mock):
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
get_current_boot_mode_mock = ilo_object_mock.get_current_boot_mode
|
||||
exc = ilo_error.IloError('error')
|
||||
get_current_boot_mode_mock.side_effect = exc
|
||||
self.assertRaises(exception.IloOperationError,
|
||||
ilo_common.get_current_boot_mode, self.node)
|
||||
get_ilo_object_mock.assert_called_once_with(self.node)
|
||||
get_current_boot_mode_mock.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(ilo_common, 'set_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
def test_update_boot_mode_instance_info_exists(self,
|
||||
|
@ -16,10 +16,12 @@
|
||||
|
||||
from unittest import mock
|
||||
|
||||
import ddt
|
||||
from oslo_utils import importutils
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from ironic.common import boot_devices
|
||||
from ironic.common import boot_modes
|
||||
from ironic.common import exception
|
||||
from ironic.common import states
|
||||
from ironic.conductor import task_manager
|
||||
@ -41,6 +43,7 @@ ilo_error = importutils.try_import('proliantutils.exception')
|
||||
INFO_DICT = db_utils.get_test_ilo_info()
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class IloManagementTestCase(test_common.BaseIloTest):
|
||||
|
||||
def setUp(self):
|
||||
@ -1181,6 +1184,88 @@ class IloManagementTestCase(test_common.BaseIloTest):
|
||||
task.driver.management.inject_nmi,
|
||||
task)
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
@ddt.data((ilo_common.SUPPORTED_BOOT_MODE_LEGACY_BIOS_ONLY,
|
||||
['bios']),
|
||||
(ilo_common.SUPPORTED_BOOT_MODE_UEFI_ONLY,
|
||||
['uefi']),
|
||||
(ilo_common.SUPPORTED_BOOT_MODE_LEGACY_BIOS_AND_UEFI,
|
||||
['uefi', 'bios']))
|
||||
@ddt.unpack
|
||||
def test_get_supported_boot_modes(self, boot_modes_val,
|
||||
exp_boot_modes,
|
||||
get_ilo_object_mock):
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
ilo_object_mock.get_supported_boot_mode.return_value = boot_modes_val
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
supported_boot_modes = (
|
||||
task.driver.management.get_supported_boot_modes(task))
|
||||
self.assertEqual(exp_boot_modes, supported_boot_modes)
|
||||
|
||||
@mock.patch.object(ilo_common, 'set_boot_mode', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(ilo_management.IloManagement,
|
||||
'get_supported_boot_modes',
|
||||
spec_set=True, autospec=True)
|
||||
def test_set_boot_mode(self, supp_boot_modes_mock,
|
||||
set_boot_mode_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
exp_boot_modes = [boot_modes.UEFI, boot_modes.LEGACY_BIOS]
|
||||
supp_boot_modes_mock.return_value = exp_boot_modes
|
||||
|
||||
for mode in exp_boot_modes:
|
||||
task.driver.management.set_boot_mode(task, mode=mode)
|
||||
supp_boot_modes_mock.assert_called_once_with(mock.ANY, task)
|
||||
set_boot_mode_mock.assert_called_once_with(task.node, mode)
|
||||
set_boot_mode_mock.reset_mock()
|
||||
supp_boot_modes_mock.reset_mock()
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(ilo_management.IloManagement,
|
||||
'get_supported_boot_modes',
|
||||
spec_set=True, autospec=True)
|
||||
def test_set_boot_mode_fail(self, supp_boot_modes_mock,
|
||||
get_ilo_object_mock):
|
||||
ilo_mock_obj = get_ilo_object_mock.return_value
|
||||
ilo_mock_obj.get_pending_boot_mode.return_value = 'legacy'
|
||||
exc = ilo_error.IloError('error')
|
||||
ilo_mock_obj.set_pending_boot_mode.side_effect = exc
|
||||
exp_boot_modes = [boot_modes.UEFI, boot_modes.LEGACY_BIOS]
|
||||
supp_boot_modes_mock.return_value = exp_boot_modes
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
self.assertRaisesRegex(
|
||||
exception.IloOperationError, 'uefi as boot mode failed',
|
||||
task.driver.management.set_boot_mode, task, boot_modes.UEFI)
|
||||
supp_boot_modes_mock.assert_called_once_with(mock.ANY, task)
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_get_boot_mode(self, get_ilo_object_mock):
|
||||
expected = 'bios'
|
||||
ilo_mock_obj = get_ilo_object_mock.return_value
|
||||
ilo_mock_obj.get_current_boot_mode.return_value = 'LEGACY'
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
response = task.driver.management.get_boot_mode(task)
|
||||
self.assertEqual(expected, response)
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_get_boot_mode_fail(self, get_ilo_object_mock):
|
||||
ilo_mock_obj = get_ilo_object_mock.return_value
|
||||
exc = ilo_error.IloError('error')
|
||||
ilo_mock_obj.get_current_boot_mode.side_effect = exc
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
self.assertRaisesRegex(
|
||||
exception.IloOperationError, 'Get current boot mode',
|
||||
task.driver.management.get_boot_mode, task)
|
||||
|
||||
|
||||
class Ilo5ManagementTestCase(db_base.DbTestCase):
|
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds support for boot mode retrieval and setting with the ``ilo`` and
|
||||
``ilo5`` hardware types.
|
Loading…
Reference in New Issue
Block a user