Merge "Implement iRMC BIOS configuration"
This commit is contained in:
commit
f70770db02
@ -18,7 +18,7 @@ Prerequisites
|
|||||||
* Install `python-scciclient <https://pypi.org/project/python-scciclient>`_
|
* Install `python-scciclient <https://pypi.org/project/python-scciclient>`_
|
||||||
and `pysnmp <https://pypi.org/project/pysnmp>`_ packages::
|
and `pysnmp <https://pypi.org/project/pysnmp>`_ packages::
|
||||||
|
|
||||||
$ pip install "python-scciclient>=0.7.0" pysnmp
|
$ pip install "python-scciclient>=0.7.1" pysnmp
|
||||||
|
|
||||||
Hardware Type
|
Hardware Type
|
||||||
=============
|
=============
|
||||||
@ -33,6 +33,10 @@ Hardware interfaces
|
|||||||
The ``irmc`` hardware type overrides the selection of the following
|
The ``irmc`` hardware type overrides the selection of the following
|
||||||
hardware interfaces:
|
hardware interfaces:
|
||||||
|
|
||||||
|
* bios
|
||||||
|
Supports ``irmc`` and ``no-bios``.
|
||||||
|
The default is ``irmc``.
|
||||||
|
|
||||||
* boot
|
* boot
|
||||||
Supports ``irmc-virtual-media``, ``irmc-pxe``, and ``pxe``.
|
Supports ``irmc-virtual-media``, ``irmc-pxe``, and ``pxe``.
|
||||||
The default is ``irmc-virtual-media``. The ``irmc-virtual-media`` boot
|
The default is ``irmc-virtual-media``. The ``irmc-virtual-media`` boot
|
||||||
@ -81,6 +85,7 @@ interfaces enabled for ``irmc`` hardware type.
|
|||||||
|
|
||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
enabled_hardware_types = irmc
|
enabled_hardware_types = irmc
|
||||||
|
enabled_bios_interfaces = irmc
|
||||||
enabled_boot_interfaces = irmc-virtual-media,irmc-pxe
|
enabled_boot_interfaces = irmc-virtual-media,irmc-pxe
|
||||||
enabled_console_interfaces = ipmitool-socat,ipmitool-shellinabox,no-console
|
enabled_console_interfaces = ipmitool-socat,ipmitool-shellinabox,no-console
|
||||||
enabled_deploy_interfaces = iscsi,direct
|
enabled_deploy_interfaces = iscsi,direct
|
||||||
@ -97,6 +102,7 @@ Here is a command example to enroll a node with ``irmc`` hardware type.
|
|||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
openstack baremetal node create --os-baremetal-api-version=1.31 \
|
openstack baremetal node create --os-baremetal-api-version=1.31 \
|
||||||
|
--bios-interface irmc \
|
||||||
--boot-interface irmc-pxe \
|
--boot-interface irmc-pxe \
|
||||||
--deploy-interface direct \
|
--deploy-interface direct \
|
||||||
--inspect-interface irmc \
|
--inspect-interface irmc \
|
||||||
@ -481,6 +487,64 @@ The RAID configuration is supported as a manual cleaning step.
|
|||||||
|
|
||||||
See :ref:`raid` for more details and examples.
|
See :ref:`raid` for more details and examples.
|
||||||
|
|
||||||
|
BIOS configuration Support
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The ``irmc`` hardware type provides the iRMC BIOS configuration with ``irmc``
|
||||||
|
bios interface.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
``irmc`` bios interface does not support``factory_reset``.
|
||||||
|
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The BIOS configuration in the iRMC driver supports the following settings:
|
||||||
|
|
||||||
|
- ``boot_option_filter``: Specifies from which drives can be booted. This
|
||||||
|
supports following options: ``UefiAndLegacy``, ``LegacyOnly``, ``UefiOnly``.
|
||||||
|
- ``check_controllers_health_status_enabled``: The UEFI FW checks the
|
||||||
|
controller health status. This supports following options: ``true``, ``false``.
|
||||||
|
- ``cpu_active_processor_cores``: The number of active processor cores 1...n.
|
||||||
|
Option 0 indicates that all available processor cores are active.
|
||||||
|
- ``cpu_adjacent_cache_line_prefetch_enabled``: The processor loads the requested
|
||||||
|
cache line and the adjacent cache line. This supports following options:
|
||||||
|
``true``, ``false``.
|
||||||
|
- ``cpu_vt_enabled``: Supports the virtualization of platform hardware and
|
||||||
|
several software environments, based on Virtual Machine Extensions to
|
||||||
|
support the use of several software environments using virtual computers.
|
||||||
|
This supports following options: ``true``, ``false``.
|
||||||
|
- ``flash_write_enabled``: The system BIOS can be written. Flash BIOS update
|
||||||
|
is possible. This supports following options: ``true``, ``false``.
|
||||||
|
- ``hyper_threading_enabled``: Hyper-threading technology allows a single
|
||||||
|
physical processor core to appear as several logical processors. This
|
||||||
|
supports following options: ``true``, ``false``.
|
||||||
|
- ``keep_void_boot_options_enabled``: Boot Options will not be removed from
|
||||||
|
"Boot Option Priority" list. This supports following options: ``true``,
|
||||||
|
``false``.
|
||||||
|
- ``launch_csm_enabled``: Specifies whether the Compatibility Support Module
|
||||||
|
(CSM) is executed. This supports following options: ``true``, ``false``.
|
||||||
|
- ``os_energy_performance_override_enabled``: Prevents the OS from overruling
|
||||||
|
any energy efficiency policy setting of the setup. This supports following
|
||||||
|
options: ``true``, ``false``.
|
||||||
|
- ``pci_aspm_support``: Active State Power Management (ASPM) is used to
|
||||||
|
power-manage the PCI Express links, thus consuming less power. This
|
||||||
|
supports following options: ``Disabled``, ``Auto``, ``L0Limited``,
|
||||||
|
``L1only``, ``L0Force``.
|
||||||
|
- ``pci_above_4g_decoding_enabled``: Specifies if memory resources above the
|
||||||
|
4GB address boundary can be assigned to PCI devices. This supports
|
||||||
|
following options: ``true``, ``false``.
|
||||||
|
- ``power_on_source``: Specifies whether the switch on sources for the system
|
||||||
|
are managed by the BIOS or the ACPI operating system. This supports
|
||||||
|
following options: ``BiosControlled``, ``AcpiControlled``.
|
||||||
|
- ``single_root_io_virtualization_support_enabled``: Single Root IO
|
||||||
|
Virtualization Support is active. This supports following
|
||||||
|
options: ``true``, ``false``.
|
||||||
|
|
||||||
|
The BIOS configuration is supported as a manual cleaning step. See :ref:`bios`
|
||||||
|
for more details and examples.
|
||||||
|
|
||||||
Supported platforms
|
Supported platforms
|
||||||
===================
|
===================
|
||||||
This driver supports FUJITSU PRIMERGY BX S4 or RX S8 servers and above.
|
This driver supports FUJITSU PRIMERGY BX S4 or RX S8 servers and above.
|
||||||
|
@ -8,7 +8,7 @@ proliantutils>=2.5.0
|
|||||||
pysnmp
|
pysnmp
|
||||||
python-ironic-inspector-client>=1.5.0
|
python-ironic-inspector-client>=1.5.0
|
||||||
python-oneviewclient<3.0.0,>=2.5.2
|
python-oneviewclient<3.0.0,>=2.5.2
|
||||||
python-scciclient>=0.7.0
|
python-scciclient>=0.7.1
|
||||||
python-ilorest-library>=2.1.0
|
python-ilorest-library>=2.1.0
|
||||||
hpOneView>=4.4.0
|
hpOneView>=4.4.0
|
||||||
UcsSdk==0.8.2.2
|
UcsSdk==0.8.2.2
|
||||||
|
@ -20,6 +20,7 @@ from ironic.drivers import generic
|
|||||||
from ironic.drivers.modules import agent
|
from ironic.drivers.modules import agent
|
||||||
from ironic.drivers.modules import inspector
|
from ironic.drivers.modules import inspector
|
||||||
from ironic.drivers.modules import ipmitool
|
from ironic.drivers.modules import ipmitool
|
||||||
|
from ironic.drivers.modules.irmc import bios
|
||||||
from ironic.drivers.modules.irmc import boot
|
from ironic.drivers.modules.irmc import boot
|
||||||
from ironic.drivers.modules.irmc import inspect
|
from ironic.drivers.modules.irmc import inspect
|
||||||
from ironic.drivers.modules.irmc import management
|
from ironic.drivers.modules.irmc import management
|
||||||
@ -36,6 +37,11 @@ class IRMCHardware(generic.GenericHardware):
|
|||||||
have iRMC S4 management system.
|
have iRMC S4 management system.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def supported_bios_interfaces(self):
|
||||||
|
"""List of supported bios interfaces."""
|
||||||
|
return [bios.IRMCBIOS, noop.NoBIOS]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_boot_interfaces(self):
|
def supported_boot_interfaces(self):
|
||||||
"""List of supported boot interfaces."""
|
"""List of supported boot interfaces."""
|
||||||
|
140
ironic/drivers/modules/irmc/bios.py
Normal file
140
ironic/drivers/modules/irmc/bios.py
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
# Copyright 2018 FUJITSU LIMITED
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""
|
||||||
|
iRMC BIOS configuration specific methods
|
||||||
|
"""
|
||||||
|
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.drivers import base
|
||||||
|
from ironic.drivers.modules.irmc import common as irmc_common
|
||||||
|
from ironic import objects
|
||||||
|
|
||||||
|
|
||||||
|
irmc = importutils.try_import('scciclient.irmc')
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
METRICS = metrics_utils.get_metrics_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class IRMCBIOS(base.BIOSInterface):
|
||||||
|
|
||||||
|
def get_properties(self):
|
||||||
|
"""Return the properties of the interface."""
|
||||||
|
return irmc_common.COMMON_PROPERTIES
|
||||||
|
|
||||||
|
@METRICS.timer('IRMCBIOS.validate')
|
||||||
|
def validate(self, task):
|
||||||
|
"""Validate the driver-specific Node info.
|
||||||
|
|
||||||
|
This method validates whether the 'driver_info' property of the
|
||||||
|
supplied node contains the required information for this driver to
|
||||||
|
manage the BIOS settings of the node.
|
||||||
|
|
||||||
|
:param task: a TaskManager instance containing the node to act on.
|
||||||
|
:raises: InvalidParameterValue if required driver_info attribute
|
||||||
|
is missing or invalid on the node.
|
||||||
|
:raises: MissingParameterValue if a required parameter is missing
|
||||||
|
in the driver_info property.
|
||||||
|
"""
|
||||||
|
irmc_common.parse_driver_info(task.node)
|
||||||
|
|
||||||
|
@METRICS.timer('IRMCBIOS.apply_configuration')
|
||||||
|
@base.clean_step(priority=0, abortable=False, argsinfo={
|
||||||
|
'settings': {
|
||||||
|
'description': "Dictionary containing the BIOS configuration.",
|
||||||
|
'required': True
|
||||||
|
}
|
||||||
|
})
|
||||||
|
def apply_configuration(self, task, settings):
|
||||||
|
"""Applies BIOS configuration on the given node.
|
||||||
|
|
||||||
|
This method takes the BIOS settings from the settings param and
|
||||||
|
applies BIOS configuration on the given node.
|
||||||
|
After the BIOS configuration is done, self.cache_bios_settings() may
|
||||||
|
be called to sync the node's BIOS-related information with the BIOS
|
||||||
|
configuration applied on the node.
|
||||||
|
It will also validate the given settings before applying any
|
||||||
|
settings and manage failures when setting an invalid BIOS config.
|
||||||
|
In the case of needing password to update the BIOS config, it will be
|
||||||
|
taken from the driver_info properties.
|
||||||
|
|
||||||
|
:param task: a TaskManager instance.
|
||||||
|
:param settings: Dictionary containing the BIOS configuration. It
|
||||||
|
may be an empty dictionary as well.
|
||||||
|
:raises: IRMCOperationError,if apply bios settings failed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
irmc_info = irmc_common.parse_driver_info(task.node)
|
||||||
|
|
||||||
|
try:
|
||||||
|
LOG.info('Apply BIOS configuration for node %(node_uuid)s: '
|
||||||
|
'%(settings)s', {'settings': settings,
|
||||||
|
'node_uuid': task.node.uuid})
|
||||||
|
irmc.elcm.set_bios_configuration(irmc_info, settings)
|
||||||
|
except irmc.scci.SCCIError as e:
|
||||||
|
LOG.error('Failed to apply BIOS configuration on node '
|
||||||
|
'%(node_uuid)s. Error: %(error)s',
|
||||||
|
{'node_uuid': task.node.uuid, 'error': e})
|
||||||
|
raise exception.IRMCOperationError(
|
||||||
|
operation='Apply BIOS configuration', error=e)
|
||||||
|
|
||||||
|
@METRICS.timer('IRMCBIOS.factory_reset')
|
||||||
|
def factory_reset(self, task):
|
||||||
|
"""Reset BIOS configuration to factory default on the given node.
|
||||||
|
|
||||||
|
:param task: a TaskManager instance.
|
||||||
|
:raises: UnsupportedDriverExtension, if the node's driver doesn't
|
||||||
|
support BIOS reset.
|
||||||
|
"""
|
||||||
|
|
||||||
|
raise exception.UnsupportedDriverExtension(
|
||||||
|
driver=task.node.driver, extension='factory_reset')
|
||||||
|
|
||||||
|
@METRICS.timer('IRMCBIOS.cache_bios_settings')
|
||||||
|
def cache_bios_settings(self, task):
|
||||||
|
"""Store or update BIOS settings on the given node.
|
||||||
|
|
||||||
|
This method stores BIOS properties to the bios settings db
|
||||||
|
|
||||||
|
:param task: a TaskManager instance.
|
||||||
|
:raises: IRMCOperationError,if get bios settings failed.
|
||||||
|
:returns: None if it is complete.
|
||||||
|
"""
|
||||||
|
|
||||||
|
irmc_info = irmc_common.parse_driver_info(task.node)
|
||||||
|
node_id = task.node.id
|
||||||
|
try:
|
||||||
|
settings = irmc.elcm.get_bios_settings(irmc_info)
|
||||||
|
except irmc.scci.SCCIError as e:
|
||||||
|
LOG.error('Failed to retrieve the current BIOS settings for node '
|
||||||
|
'%(node)s. Error: %(error)s', {'node': task.node.uuid,
|
||||||
|
'error': e})
|
||||||
|
raise exception.IRMCOperationError(operation='Cache BIOS settings',
|
||||||
|
error=e)
|
||||||
|
create_list, update_list, delete_list, nochange_list = (
|
||||||
|
objects.BIOSSettingList.sync_node_setting(task.context, node_id,
|
||||||
|
settings))
|
||||||
|
if len(create_list) > 0:
|
||||||
|
objects.BIOSSettingList.create(task.context, node_id, create_list)
|
||||||
|
if len(update_list) > 0:
|
||||||
|
objects.BIOSSettingList.save(task.context, node_id, update_list)
|
||||||
|
if len(delete_list) > 0:
|
||||||
|
delete_names = [setting['name'] for setting in delete_list]
|
||||||
|
objects.BIOSSettingList.delete(task.context, node_id,
|
||||||
|
delete_names)
|
152
ironic/tests/unit/drivers/modules/irmc/test_bios.py
Normal file
152
ironic/tests/unit/drivers/modules/irmc/test_bios.py
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
# Copyright 2018 FUJITSU LIMITED
|
||||||
|
#
|
||||||
|
# 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 IRMC BIOS configuration
|
||||||
|
"""
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from ironic.common import exception
|
||||||
|
from ironic.conductor import task_manager
|
||||||
|
from ironic.drivers.modules.irmc import bios as irmc_bios
|
||||||
|
from ironic.drivers.modules.irmc import common as irmc_common
|
||||||
|
from ironic import objects
|
||||||
|
from ironic.tests.unit.drivers.modules.irmc import test_common
|
||||||
|
|
||||||
|
|
||||||
|
class IRMCBIOSTestCase(test_common.BaseIRMCTest):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(IRMCBIOSTestCase, self).setUp()
|
||||||
|
self.config(enabled_bios_interfaces=['irmc'])
|
||||||
|
|
||||||
|
@mock.patch.object(irmc_common, 'parse_driver_info',
|
||||||
|
autospec=True)
|
||||||
|
def test_validate(self, parse_driver_info_mock):
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
|
task.driver.bios.validate(task)
|
||||||
|
parse_driver_info_mock.assert_called_once_with(task.node)
|
||||||
|
|
||||||
|
@mock.patch.object(irmc_bios.irmc.elcm, 'set_bios_configuration',
|
||||||
|
autospec=True)
|
||||||
|
def test_apply_configuration(self, set_bios_configuration_mock):
|
||||||
|
settings = [{
|
||||||
|
"name": "launch_csm_enabled",
|
||||||
|
"value": True
|
||||||
|
}, {
|
||||||
|
"name": "hyper_threading_enabled",
|
||||||
|
"value": True
|
||||||
|
}, {
|
||||||
|
"name": "cpu_vt_enabled",
|
||||||
|
"value": True
|
||||||
|
}]
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
|
irmc_info = irmc_common.parse_driver_info(task.node)
|
||||||
|
task.driver.bios.apply_configuration(task, settings)
|
||||||
|
set_bios_configuration_mock.assert_called_once_with(irmc_info,
|
||||||
|
settings)
|
||||||
|
|
||||||
|
@mock.patch.object(irmc_bios.irmc.elcm, 'set_bios_configuration',
|
||||||
|
autospec=True)
|
||||||
|
def test_apply_configuration_failed(self, set_bios_configuration_mock):
|
||||||
|
settings = [{
|
||||||
|
"name": "launch_csm_enabled",
|
||||||
|
"value": True
|
||||||
|
}, {
|
||||||
|
"name": "hyper_threading_enabled",
|
||||||
|
"value": True
|
||||||
|
}, {
|
||||||
|
"name": "setting",
|
||||||
|
"value": True
|
||||||
|
}]
|
||||||
|
irmc_bios.irmc.scci.SCCIError = Exception
|
||||||
|
set_bios_configuration_mock.side_effect = Exception
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
|
self.assertRaises(exception.IRMCOperationError,
|
||||||
|
task.driver.bios.apply_configuration,
|
||||||
|
task, settings)
|
||||||
|
|
||||||
|
def test_factory_reset(self):
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
|
self.assertRaises(exception.UnsupportedDriverExtension,
|
||||||
|
task.driver.bios.factory_reset, task)
|
||||||
|
|
||||||
|
@mock.patch.object(objects.BIOSSettingList, 'sync_node_setting')
|
||||||
|
@mock.patch.object(objects.BIOSSettingList, 'create')
|
||||||
|
@mock.patch.object(objects.BIOSSettingList, 'save')
|
||||||
|
@mock.patch.object(objects.BIOSSettingList, 'delete')
|
||||||
|
@mock.patch.object(irmc_bios.irmc.elcm, 'get_bios_settings',
|
||||||
|
autospec=True)
|
||||||
|
def test_cache_bios_settings(self, get_bios_settings_mock,
|
||||||
|
delete_mock, save_mock, create_mock,
|
||||||
|
sync_node_setting_mock):
|
||||||
|
settings = [{
|
||||||
|
"name": "launch_csm_enabled",
|
||||||
|
"value": True
|
||||||
|
}, {
|
||||||
|
"name": "hyper_threading_enabled",
|
||||||
|
"value": True
|
||||||
|
}, {
|
||||||
|
"name": "cpu_vt_enabled",
|
||||||
|
"value": True
|
||||||
|
}]
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
|
irmc_info = irmc_common.parse_driver_info(task.node)
|
||||||
|
get_bios_settings_mock.return_value = settings
|
||||||
|
sync_node_setting_mock.return_value = \
|
||||||
|
(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "launch_csm_enabled",
|
||||||
|
"value": True
|
||||||
|
}],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "hyper_threading_enabled",
|
||||||
|
"value": True
|
||||||
|
}],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "cpu_vt_enabled",
|
||||||
|
"value": True
|
||||||
|
}],
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
task.driver.bios.cache_bios_settings(task)
|
||||||
|
get_bios_settings_mock.assert_called_once_with(irmc_info)
|
||||||
|
sync_node_setting_mock.assert_called_once_with(task.context,
|
||||||
|
task.node.id,
|
||||||
|
settings)
|
||||||
|
create_mock.assert_called_once_with(
|
||||||
|
task.context, task.node.id,
|
||||||
|
sync_node_setting_mock.return_value[0])
|
||||||
|
save_mock.assert_called_once_with(
|
||||||
|
task.context, task.node.id,
|
||||||
|
sync_node_setting_mock.return_value[1])
|
||||||
|
delete_names = \
|
||||||
|
[setting['name'] for setting in
|
||||||
|
sync_node_setting_mock.return_value[2]]
|
||||||
|
delete_mock.assert_called_once_with(task.context, task.node.id,
|
||||||
|
delete_names)
|
||||||
|
|
||||||
|
@mock.patch.object(irmc_bios.irmc.elcm, 'get_bios_settings',
|
||||||
|
autospec=True)
|
||||||
|
def test_cache_bios_settings_failed(self, get_bios_settings_mock):
|
||||||
|
irmc_bios.irmc.scci.SCCIError = Exception
|
||||||
|
get_bios_settings_mock.side_effect = Exception
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||||
|
self.assertRaises(exception.IRMCOperationError,
|
||||||
|
task.driver.bios.cache_bios_settings,
|
||||||
|
task)
|
@ -39,6 +39,7 @@ class BaseIRMCTest(db_base.DbTestCase):
|
|||||||
self.config(enabled_hardware_types=['irmc', 'fake-hardware'],
|
self.config(enabled_hardware_types=['irmc', 'fake-hardware'],
|
||||||
enabled_power_interfaces=['irmc', 'fake'],
|
enabled_power_interfaces=['irmc', 'fake'],
|
||||||
enabled_management_interfaces=['irmc', 'fake'],
|
enabled_management_interfaces=['irmc', 'fake'],
|
||||||
|
enabled_bios_interfaces=['irmc', 'no-bios', 'fake'],
|
||||||
enabled_boot_interfaces=[self.boot_interface, 'fake'],
|
enabled_boot_interfaces=[self.boot_interface, 'fake'],
|
||||||
enabled_inspect_interfaces=['irmc', 'no-inspect', 'fake'])
|
enabled_inspect_interfaces=['irmc', 'no-inspect', 'fake'])
|
||||||
self.info = db_utils.get_test_irmc_info()
|
self.info = db_utils.get_test_irmc_info()
|
||||||
|
@ -21,6 +21,7 @@ from ironic.drivers import irmc
|
|||||||
from ironic.drivers.modules import agent
|
from ironic.drivers.modules import agent
|
||||||
from ironic.drivers.modules import inspector
|
from ironic.drivers.modules import inspector
|
||||||
from ironic.drivers.modules import ipmitool
|
from ironic.drivers.modules import ipmitool
|
||||||
|
from ironic.drivers.modules.irmc import bios as irmc_bios
|
||||||
from ironic.drivers.modules.irmc import raid
|
from ironic.drivers.modules.irmc import raid
|
||||||
from ironic.drivers.modules import iscsi_deploy
|
from ironic.drivers.modules import iscsi_deploy
|
||||||
from ironic.drivers.modules import noop
|
from ironic.drivers.modules import noop
|
||||||
@ -42,7 +43,8 @@ class IRMCHardwareTestCase(db_base.DbTestCase):
|
|||||||
enabled_management_interfaces=['irmc'],
|
enabled_management_interfaces=['irmc'],
|
||||||
enabled_power_interfaces=['irmc', 'ipmitool'],
|
enabled_power_interfaces=['irmc', 'ipmitool'],
|
||||||
enabled_raid_interfaces=['no-raid', 'agent', 'irmc'],
|
enabled_raid_interfaces=['no-raid', 'agent', 'irmc'],
|
||||||
enabled_rescue_interfaces=['no-rescue', 'agent'])
|
enabled_rescue_interfaces=['no-rescue', 'agent'],
|
||||||
|
enabled_bios_interfaces=['irmc', 'no-bios', 'fake'])
|
||||||
|
|
||||||
def test_default_interfaces(self):
|
def test_default_interfaces(self):
|
||||||
node = obj_utils.create_test_node(self.context, driver='irmc')
|
node = obj_utils.create_test_node(self.context, driver='irmc')
|
||||||
@ -63,6 +65,8 @@ class IRMCHardwareTestCase(db_base.DbTestCase):
|
|||||||
noop.NoRAID)
|
noop.NoRAID)
|
||||||
self.assertIsInstance(task.driver.rescue,
|
self.assertIsInstance(task.driver.rescue,
|
||||||
noop.NoRescue)
|
noop.NoRescue)
|
||||||
|
self.assertIsInstance(task.driver.bios,
|
||||||
|
irmc_bios.IRMCBIOS)
|
||||||
|
|
||||||
def test_override_with_inspector(self):
|
def test_override_with_inspector(self):
|
||||||
self.config(enabled_inspect_interfaces=['inspector', 'irmc'])
|
self.config(enabled_inspect_interfaces=['inspector', 'irmc'])
|
||||||
@ -157,3 +161,27 @@ class IRMCHardwareTestCase(db_base.DbTestCase):
|
|||||||
raid.IRMCRAID)
|
raid.IRMCRAID)
|
||||||
self.assertIsInstance(task.driver.rescue,
|
self.assertIsInstance(task.driver.rescue,
|
||||||
agent.AgentRescue)
|
agent.AgentRescue)
|
||||||
|
|
||||||
|
def test_override_with_bios_configuration(self):
|
||||||
|
node = obj_utils.create_test_node(
|
||||||
|
self.context, driver='irmc',
|
||||||
|
deploy_interface='direct',
|
||||||
|
rescue_interface='agent',
|
||||||
|
bios_interface='irmc')
|
||||||
|
with task_manager.acquire(self.context, node.id) as task:
|
||||||
|
self.assertIsInstance(task.driver.boot,
|
||||||
|
irmc.boot.IRMCVirtualMediaBoot)
|
||||||
|
self.assertIsInstance(task.driver.console,
|
||||||
|
ipmitool.IPMISocatConsole)
|
||||||
|
self.assertIsInstance(task.driver.deploy,
|
||||||
|
agent.AgentDeploy)
|
||||||
|
self.assertIsInstance(task.driver.inspect,
|
||||||
|
irmc.inspect.IRMCInspect)
|
||||||
|
self.assertIsInstance(task.driver.management,
|
||||||
|
irmc.management.IRMCManagement)
|
||||||
|
self.assertIsInstance(task.driver.power,
|
||||||
|
irmc.power.IRMCPower)
|
||||||
|
self.assertIsInstance(task.driver.bios,
|
||||||
|
irmc_bios.IRMCBIOS)
|
||||||
|
self.assertIsInstance(task.driver.rescue,
|
||||||
|
agent.AgentRescue)
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Adds new ``bios`` interface to ``irmc`` hardware type. And provide
|
||||||
|
out-of-band BIOS configuration solution for iRMC driver which makes
|
||||||
|
the functionality available via manual cleaning.
|
@ -54,6 +54,7 @@ ironic.dhcp =
|
|||||||
|
|
||||||
ironic.hardware.interfaces.bios =
|
ironic.hardware.interfaces.bios =
|
||||||
fake = ironic.drivers.modules.fake:FakeBIOS
|
fake = ironic.drivers.modules.fake:FakeBIOS
|
||||||
|
irmc = ironic.drivers.modules.irmc.bios:IRMCBIOS
|
||||||
no-bios = ironic.drivers.modules.noop:NoBIOS
|
no-bios = ironic.drivers.modules.noop:NoBIOS
|
||||||
|
|
||||||
ironic.hardware.interfaces.boot =
|
ironic.hardware.interfaces.boot =
|
||||||
|
Loading…
Reference in New Issue
Block a user