iLO BIOS interface implementation
Adds support for manual cleaning steps "apply_configuration" and "factory_reset" which manage BIOS settings on the iLO. This requires to implement 'ilo' BIOS interface for 'ilo' hardware type. Story: #2002899 Task: #22863 Change-Id: Ia014ea3d55504e8e0c815fb4f19bb87b1fc0d6ef
This commit is contained in:
parent
afbe8e7679
commit
66e1ccb7c5
@ -4,7 +4,7 @@
|
||||
# python projects they should package as optional dependencies for Ironic.
|
||||
|
||||
# These are available on pypi
|
||||
proliantutils>=2.5.0
|
||||
proliantutils>=2.6.0
|
||||
pysnmp>=4.3.0,<5.0.0
|
||||
python-ironic-inspector-client>=1.5.0
|
||||
python-oneviewclient<3.0.0,>=2.5.2
|
||||
|
@ -16,6 +16,7 @@ iLO Driver for managing HP Proliant Gen8 and above servers.
|
||||
"""
|
||||
|
||||
from ironic.drivers import generic
|
||||
from ironic.drivers.modules.ilo import bios
|
||||
from ironic.drivers.modules.ilo import boot
|
||||
from ironic.drivers.modules.ilo import console
|
||||
from ironic.drivers.modules.ilo import inspect
|
||||
@ -38,6 +39,11 @@ class IloHardware(generic.GenericHardware):
|
||||
"""List of supported boot interfaces."""
|
||||
return [boot.IloVirtualMediaBoot, boot.IloPXEBoot]
|
||||
|
||||
@property
|
||||
def supported_bios_interfaces(self):
|
||||
"""List of supported bios interfaces."""
|
||||
return [bios.IloBIOS, noop.NoBIOS]
|
||||
|
||||
@property
|
||||
def supported_console_interfaces(self):
|
||||
"""List of supported console interfaces."""
|
||||
|
157
ironic/drivers/modules/ilo/bios.py
Normal file
157
ironic/drivers/modules/ilo/bios.py
Normal file
@ -0,0 +1,157 @@
|
||||
# Copyright 2018 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
"""
|
||||
iLO BIOS Interface
|
||||
"""
|
||||
|
||||
from ironic_lib import metrics_utils
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import importutils
|
||||
|
||||
from ironic.common import exception
|
||||
from ironic.common.i18n import _
|
||||
from ironic.drivers import base
|
||||
from ironic.drivers.modules.ilo import common as ilo_common
|
||||
from ironic import objects
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
METRICS = metrics_utils.get_metrics_logger(__name__)
|
||||
|
||||
ilo_error = importutils.try_import('proliantutils.exception')
|
||||
|
||||
|
||||
class IloBIOS(base.BIOSInterface):
|
||||
|
||||
def get_properties(self):
|
||||
return ilo_common.REQUIRED_PROPERTIES
|
||||
|
||||
@METRICS.timer('IloBIOS.validate')
|
||||
def validate(self, task):
|
||||
"""Check that 'driver_info' contains required ILO credentials.
|
||||
|
||||
Validates whether the 'driver_info' property of the supplied
|
||||
task's node contains the required credentials information.
|
||||
|
||||
:param task: a task from TaskManager.
|
||||
:raises: InvalidParameterValue if required iLO parameters
|
||||
are not valid.
|
||||
:raises: MissingParameterValue if a required parameter is missing.
|
||||
"""
|
||||
ilo_common.parse_driver_info(task.node)
|
||||
|
||||
@METRICS.timer('IloBIOS.apply_configuration')
|
||||
@base.clean_step(priority=0, abortable=False, argsinfo={
|
||||
'settings': {
|
||||
'description': "Dictionary with current BIOS configuration.",
|
||||
'required': True
|
||||
}
|
||||
})
|
||||
def apply_configuration(self, task, settings):
|
||||
"""Applies the provided configuration on the node.
|
||||
|
||||
:param task: a TaskManager instance.
|
||||
:param settings: Settings intended to be applied on the node.
|
||||
:raises: NodeCleaningFailure when applying the configuration on
|
||||
the node fails.
|
||||
|
||||
"""
|
||||
data = {}
|
||||
for setting in settings:
|
||||
data.update({setting['name']: setting['value']})
|
||||
|
||||
node = task.node
|
||||
|
||||
errmsg = _("Clean step \"apply_configuration\" failed "
|
||||
"on node %(node)s with error: %(err)s")
|
||||
|
||||
try:
|
||||
ilo_object = ilo_common.get_ilo_object(node)
|
||||
ilo_object.set_bios_settings(data)
|
||||
except (exception.MissingParameterValue,
|
||||
exception.InvalidParameterValue,
|
||||
ilo_error.IloError,
|
||||
ilo_error.IloCommandNotSupportedError) as ir_exception:
|
||||
raise exception.NodeCleaningFailure(
|
||||
errmsg % {'node': node.uuid, 'err': ir_exception})
|
||||
|
||||
@METRICS.timer('IloBIOS.factory_reset')
|
||||
@base.clean_step(priority=0, abortable=False)
|
||||
def factory_reset(self, task):
|
||||
"""Reset the BIOS settings to factory configuration.
|
||||
|
||||
:param task: a TaskManager instance.
|
||||
:raises: NodeCleaningFailure when IloError or any other exception
|
||||
is caught.
|
||||
|
||||
"""
|
||||
node = task.node
|
||||
|
||||
errmsg = _("Clean step \"factory_reset\" failed "
|
||||
"on node %(node)s with error: %(err)s")
|
||||
|
||||
try:
|
||||
ilo_object = ilo_common.get_ilo_object(node)
|
||||
ilo_object.reset_bios_to_default()
|
||||
except (exception.MissingParameterValue,
|
||||
exception.InvalidParameterValue,
|
||||
ilo_error.IloError,
|
||||
ilo_error.IloCommandNotSupportedError) as ir_exception:
|
||||
raise exception.NodeCleaningFailure(
|
||||
errmsg % {'node': node.uuid, 'err': ir_exception})
|
||||
|
||||
@METRICS.timer('IloBIOS.cache_bios_settings')
|
||||
def cache_bios_settings(self, task):
|
||||
"""Store the BIOS settings in the database.
|
||||
|
||||
:param task: a TaskManager instance.
|
||||
:raises: NodeCleaningFailure when IloError or any other exception
|
||||
is caught.
|
||||
|
||||
"""
|
||||
node = task.node
|
||||
nodeid = node.id
|
||||
|
||||
errmsg = _("Caching BIOS settings failed "
|
||||
"on node %(node)s with error: %(err)s")
|
||||
try:
|
||||
ilo_object = ilo_common.get_ilo_object(node)
|
||||
bios_settings = ilo_object.get_pending_bios_settings()
|
||||
|
||||
except (exception.MissingParameterValue,
|
||||
exception.InvalidParameterValue,
|
||||
ilo_error.IloError,
|
||||
ilo_error.IloCommandNotSupportedError) as ir_exception:
|
||||
raise exception.NodeCleaningFailure(
|
||||
errmsg % {'node': node.uuid, 'err': ir_exception})
|
||||
|
||||
fmt_bios_settings = []
|
||||
|
||||
for setting in bios_settings:
|
||||
fmt_bios_settings.append({"name": setting,
|
||||
"value": bios_settings[setting]})
|
||||
|
||||
create_list, update_list, delete_list, nochange_list = (
|
||||
objects.BIOSSettingList.sync_node_setting(task.context,
|
||||
nodeid,
|
||||
fmt_bios_settings))
|
||||
if len(create_list) > 0:
|
||||
objects.BIOSSettingList.create(task.context, nodeid, create_list)
|
||||
if len(update_list) > 0:
|
||||
objects.BIOSSettingList.save(task.context, nodeid, update_list)
|
||||
if len(delete_list) > 0:
|
||||
delete_name_list = [delete_name.get(
|
||||
"name") for delete_name in delete_list]
|
||||
objects.BIOSSettingList.delete(
|
||||
task.context, nodeid, delete_name_list)
|
287
ironic/tests/unit/drivers/modules/ilo/test_bios.py
Normal file
287
ironic/tests/unit/drivers/modules/ilo/test_bios.py
Normal file
@ -0,0 +1,287 @@
|
||||
# Copyright 2018 Hewlett-Packard Development Company, L.P.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""Test class for IloPower module."""
|
||||
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import importutils
|
||||
|
||||
from ironic.common import exception
|
||||
from ironic.conductor import task_manager
|
||||
from ironic.drivers.modules.ilo import common as ilo_common
|
||||
from ironic import objects
|
||||
from ironic.tests.unit.db import utils as db_utils
|
||||
from ironic.tests.unit.drivers.modules.ilo import test_common
|
||||
|
||||
ilo_error = importutils.try_import('proliantutils.exception')
|
||||
|
||||
INFO_DICT = db_utils.get_test_ilo_info()
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class IloBiosTestCase(test_common.BaseIloTest):
|
||||
|
||||
def test_get_properties(self):
|
||||
expected = ilo_common.REQUIRED_PROPERTIES
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
self.assertEqual(expected, task.driver.bios.get_properties())
|
||||
|
||||
@mock.patch.object(ilo_common, 'parse_driver_info', spec_set=True,
|
||||
autospec=True)
|
||||
def test_validate(self, mock_drvinfo):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
task.driver.bios.validate(task)
|
||||
mock_drvinfo.assert_called_once_with(task.node)
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def _test_ilo_error(self, error_type,
|
||||
test_methods_not_called, method_details, ilo_mock):
|
||||
error_dict = {
|
||||
"missing_parameter": exception.MissingParameterValue,
|
||||
"invalid_parameter": exception.InvalidParameterValue
|
||||
}
|
||||
|
||||
exc = error_dict.get(error_type)('error')
|
||||
ilo_mock.side_effect = exc
|
||||
method = method_details.get("name")
|
||||
args = method_details.get("args")
|
||||
self.assertRaises(exception.NodeCleaningFailure,
|
||||
method,
|
||||
*args)
|
||||
for test_method in test_methods_not_called:
|
||||
eval("ilo_mock.return_value.%s.assert_not_called()" % (
|
||||
test_method))
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_apply_configuration(self, get_ilo_object_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
data = [
|
||||
{
|
||||
"name": "SET_A", "value": "VAL_A",
|
||||
},
|
||||
{
|
||||
"name": "SET_B", "value": "VAL_B",
|
||||
},
|
||||
{
|
||||
"name": "SET_C", "value": "VAL_C",
|
||||
},
|
||||
{
|
||||
"name": "SET_D", "value": "VAL_D",
|
||||
}
|
||||
]
|
||||
task.driver.bios.apply_configuration(task, data)
|
||||
expected = {
|
||||
"SET_A": "VAL_A",
|
||||
"SET_B": "VAL_B",
|
||||
"SET_C": "VAL_C",
|
||||
"SET_D": "VAL_D"
|
||||
}
|
||||
ilo_object_mock.set_bios_settings.assert_called_once_with(expected)
|
||||
|
||||
def test_apply_configuration_missing_parameter(self):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
mdobj = {
|
||||
"name": task.driver.bios.apply_configuration,
|
||||
"args": (task, [])
|
||||
}
|
||||
self._test_ilo_error("missing_parameter", ["set_bios_settings"],
|
||||
mdobj)
|
||||
|
||||
def test_apply_configuration_invalid_parameter(self):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
mdobj = {
|
||||
"name": task.driver.bios.apply_configuration,
|
||||
"args": (task, [])
|
||||
}
|
||||
self._test_ilo_error("invalid_parameter", ["set_bios_settings"],
|
||||
mdobj)
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_apply_configuration_with_ilo_error(self, get_ilo_object_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
data = [
|
||||
{
|
||||
"name": "SET_A", "value": "VAL_A",
|
||||
},
|
||||
{
|
||||
"name": "SET_B", "value": "VAL_B",
|
||||
},
|
||||
]
|
||||
exc = ilo_error.IloError('error')
|
||||
ilo_object_mock.set_bios_settings.side_effect = exc
|
||||
self.assertRaises(exception.NodeCleaningFailure,
|
||||
task.driver.bios.apply_configuration,
|
||||
task, data)
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_factory_reset(self, get_ilo_object_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
task.driver.bios.factory_reset(task)
|
||||
ilo_object_mock.reset_bios_to_default.assert_called_once_with()
|
||||
|
||||
def test_factory_reset_missing_parameter(self):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
mdobj = {
|
||||
"name": task.driver.bios.factory_reset,
|
||||
"args": (task,)
|
||||
}
|
||||
self._test_ilo_error("missing_parameter",
|
||||
["reset_bios_to_default"], mdobj)
|
||||
|
||||
def test_factory_reset_invalid_parameter(self):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
mdobj = {
|
||||
"name": task.driver.bios.factory_reset,
|
||||
"args": (task,)
|
||||
}
|
||||
self._test_ilo_error("invalid_parameter",
|
||||
["reset_bios_to_default"], mdobj)
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_factory_reset_with_ilo_error(self, get_ilo_object_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
exc = ilo_error.IloError('error')
|
||||
ilo_object_mock.reset_bios_to_default.side_effect = exc
|
||||
self.assertRaises(exception.NodeCleaningFailure,
|
||||
task.driver.bios.factory_reset, task)
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test_factory_reset_with_unknown_error(self, get_ilo_object_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
exc = ilo_error.IloCommandNotSupportedError('error')
|
||||
ilo_object_mock.reset_bios_to_default.side_effect = exc
|
||||
self.assertRaises(exception.NodeCleaningFailure,
|
||||
task.driver.bios.factory_reset, task)
|
||||
|
||||
@mock.patch.object(objects.BIOSSettingList, 'create')
|
||||
@mock.patch.object(objects.BIOSSettingList, 'save')
|
||||
@mock.patch.object(objects.BIOSSettingList, 'delete')
|
||||
@mock.patch.object(objects.BIOSSettingList, 'sync_node_setting')
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', autospec=True)
|
||||
def test_cache_bios_settings(self, get_ilo_object_mock, sync_node_mock,
|
||||
delete_mock, save_mock, create_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
settings = {
|
||||
"SET_A": True,
|
||||
"SET_B": True,
|
||||
"SET_C": True,
|
||||
"SET_D": True
|
||||
}
|
||||
|
||||
ilo_object_mock.get_pending_bios_settings.return_value = settings
|
||||
expected_bios_settings = [
|
||||
{"name": "SET_A", "value": True},
|
||||
{"name": "SET_B", "value": True},
|
||||
{"name": "SET_C", "value": True},
|
||||
{"name": "SET_D", "value": True}
|
||||
]
|
||||
sync_node_mock.return_value = ([], [], [], [])
|
||||
all_settings = (
|
||||
[
|
||||
{"name": "C_1", "value": "C_1_VAL"},
|
||||
{"name": "C_2", "value": "C_2_VAL"}
|
||||
],
|
||||
[
|
||||
{"name": "U_1", "value": "U_1_VAL"},
|
||||
{"name": "U_2", "value": "U_2_VAL"}
|
||||
],
|
||||
[
|
||||
{"name": "D_1", "value": "D_1_VAL"},
|
||||
{"name": "D_2", "value": "D_2_VAL"}
|
||||
],
|
||||
[]
|
||||
)
|
||||
sync_node_mock.return_value = all_settings
|
||||
task.driver.bios.cache_bios_settings(task)
|
||||
ilo_object_mock.get_pending_bios_settings.assert_called_once_with()
|
||||
actual_arg = sorted(sync_node_mock.call_args[0][2],
|
||||
key=lambda x: x.get("name"))
|
||||
expected_arg = sorted(expected_bios_settings,
|
||||
key=lambda x: x.get("name"))
|
||||
self.assertEqual(actual_arg, expected_arg)
|
||||
create_mock.assert_called_once_with(
|
||||
self.context, task.node.id, all_settings[0])
|
||||
save_mock.assert_called_once_with(
|
||||
self.context, task.node.id, all_settings[1])
|
||||
del_names = [setting.get("name") for setting in all_settings[2]]
|
||||
delete_mock.assert_called_once_with(
|
||||
self.context, task.node.id, del_names)
|
||||
|
||||
def test_cache_bios_settings_missing_parameter(self):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
mdobj = {
|
||||
"name": task.driver.bios.cache_bios_settings,
|
||||
"args": (task,)
|
||||
}
|
||||
self._test_ilo_error("missing_parameter",
|
||||
["get_pending_bios_settings"], mdobj)
|
||||
|
||||
def test_cache_bios_settings_invalid_parameter(self):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
mdobj = {
|
||||
"name": task.driver.bios.cache_bios_settings,
|
||||
"args": (task,)
|
||||
}
|
||||
self._test_ilo_error("invalid_parameter",
|
||||
["get_pending_bios_settings"], mdobj)
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', autospec=True)
|
||||
def test_cache_bios_settings_with_ilo_error(self, get_ilo_object_mock):
|
||||
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
exc = ilo_error.IloError('error')
|
||||
ilo_object_mock.get_pending_bios_settings.side_effect = exc
|
||||
self.assertRaises(exception.NodeCleaningFailure,
|
||||
task.driver.bios.cache_bios_settings, task)
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', autospec=True)
|
||||
def test_cache_bios_settings_with_unknown_error(self, get_ilo_object_mock):
|
||||
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
ilo_object_mock = get_ilo_object_mock.return_value
|
||||
exc = ilo_error.IloCommandNotSupportedError('error')
|
||||
ilo_object_mock.get_pending_bios_settings.side_effect = exc
|
||||
self.assertRaises(exception.NodeCleaningFailure,
|
||||
task.driver.bios.cache_bios_settings, task)
|
@ -62,6 +62,7 @@ class BaseIloTest(db_base.DbTestCase):
|
||||
self.config(enabled_hardware_types=['ilo', 'fake-hardware'],
|
||||
enabled_boot_interfaces=['ilo-pxe', 'ilo-virtual-media',
|
||||
'fake'],
|
||||
enabled_bios_interfaces=['ilo', 'no-bios'],
|
||||
enabled_power_interfaces=['ilo', 'fake'],
|
||||
enabled_management_interfaces=['ilo', 'fake'],
|
||||
enabled_inspect_interfaces=['ilo', 'fake', 'no-inspect'],
|
||||
@ -71,6 +72,7 @@ class BaseIloTest(db_base.DbTestCase):
|
||||
self.node = obj_utils.create_test_node(
|
||||
self.context, uuid=uuidutils.generate_uuid(),
|
||||
driver='ilo', boot_interface=self.boot_interface,
|
||||
bios_interface='ilo',
|
||||
driver_info=self.info)
|
||||
|
||||
|
||||
|
@ -32,6 +32,7 @@ class IloHardwareTestCase(db_base.DbTestCase):
|
||||
super(IloHardwareTestCase, self).setUp()
|
||||
self.config(enabled_hardware_types=['ilo'],
|
||||
enabled_boot_interfaces=['ilo-virtual-media', 'ilo-pxe'],
|
||||
enabled_bios_interfaces=['no-bios', 'ilo'],
|
||||
enabled_console_interfaces=['ilo'],
|
||||
enabled_deploy_interfaces=['iscsi', 'direct'],
|
||||
enabled_inspect_interfaces=['ilo'],
|
||||
@ -47,6 +48,8 @@ class IloHardwareTestCase(db_base.DbTestCase):
|
||||
with task_manager.acquire(self.context, node.id) as task:
|
||||
self.assertIsInstance(task.driver.boot,
|
||||
ilo.boot.IloVirtualMediaBoot)
|
||||
self.assertIsInstance(task.driver.bios,
|
||||
ilo.bios.IloBIOS)
|
||||
self.assertIsInstance(task.driver.console,
|
||||
ilo.console.IloConsoleInterface)
|
||||
self.assertIsInstance(task.driver.deploy,
|
||||
@ -143,3 +146,22 @@ class IloHardwareTestCase(db_base.DbTestCase):
|
||||
agent.AgentRescue)
|
||||
self.assertIsInstance(task.driver.vendor,
|
||||
ilo.vendor.VendorPassthru)
|
||||
|
||||
def test_override_with_no_bios(self):
|
||||
node = obj_utils.create_test_node(
|
||||
self.context, driver='ilo',
|
||||
boot_interface='ilo-pxe',
|
||||
bios_interface='no-bios',
|
||||
deploy_interface='direct',
|
||||
raid_interface='agent')
|
||||
with task_manager.acquire(self.context, node.id) as task:
|
||||
self.assertIsInstance(task.driver.boot,
|
||||
ilo.boot.IloPXEBoot)
|
||||
self.assertIsInstance(task.driver.bios,
|
||||
noop.NoBIOS)
|
||||
self.assertIsInstance(task.driver.console,
|
||||
ilo.console.IloConsoleInterface)
|
||||
self.assertIsInstance(task.driver.deploy,
|
||||
agent.AgentDeploy)
|
||||
self.assertIsInstance(task.driver.raid,
|
||||
agent.AgentRAID)
|
||||
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Implements ``bios`` interface for ``ilo`` hardware type.
|
||||
Adds the list of supported bios interfaces for the `ilo` hardware type.
|
||||
Adds manual cleaning steps ``apply_configuration`` and ``factory_reset``
|
||||
which support managing the BIOS settings for the iLO servers using `ilo`
|
||||
hardware type.
|
Loading…
Reference in New Issue
Block a user