Add additional capabilities discovery for iRMC driver
This update enhances iRMC out-of-band hardware inspection for FUJITSU PRIMERGY bare metal nodes having iRMC S4 and beyond. The capabilities are server_model, rom_firmware_version, pci_gpu_devices, trusted_boot and irmc_firmware_version. Co-authored-By: Nguyen Van Trung <trungnv@vn.fujitsu.com> Change-Id: I1958e18a5b9d933e2aa405b200bac7717f146611 Closes-Bug: #1637422
This commit is contained in:
parent
459d1c2d3e
commit
7adbf11bb8
|
@ -26,7 +26,7 @@ Prerequisites
|
||||||
* Install `python-scciclient <https://pypi.python.org/pypi/python-scciclient>`_
|
* Install `python-scciclient <https://pypi.python.org/pypi/python-scciclient>`_
|
||||||
and `pysnmp <https://pypi.python.org/pypi/pysnmp>`_ packages::
|
and `pysnmp <https://pypi.python.org/pypi/pysnmp>`_ packages::
|
||||||
|
|
||||||
$ pip install "python-scciclient>=0.5.0" pysnmp
|
$ pip install "python-scciclient>=0.6.0" pysnmp
|
||||||
|
|
||||||
Hardware Type
|
Hardware Type
|
||||||
=============
|
=============
|
||||||
|
@ -62,7 +62,7 @@ hardware interfaces:
|
||||||
Supports ``irmc``, ``inspector``, and ``no-inspect``.
|
Supports ``irmc``, ``inspector``, and ``no-inspect``.
|
||||||
The default is ``irmc``.
|
The default is ``irmc``.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
`Ironic Inspector <https://docs.openstack.org/ironic-inspector/latest/>`_
|
`Ironic Inspector <https://docs.openstack.org/ironic-inspector/latest/>`_
|
||||||
needs to be present and configured to use ``inspector`` as the
|
needs to be present and configured to use ``inspector`` as the
|
||||||
inspect interface.
|
inspect interface.
|
||||||
|
@ -491,6 +491,93 @@ The drivers support the PCI controllers, Fibrechannel Cards, Converged Network
|
||||||
Adapters supported by
|
Adapters supported by
|
||||||
`Fujitsu ServerView Virtual-IO Manager <http://www.fujitsu.com/fts/products/computing/servers/primergy/management/primergy-blade-server-io-virtualization.html>`_.
|
`Fujitsu ServerView Virtual-IO Manager <http://www.fujitsu.com/fts/products/computing/servers/primergy/management/primergy-blade-server-io-virtualization.html>`_.
|
||||||
|
|
||||||
|
Hardware Inspection Support
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The ``irmc`` hardware type (only ``irmc`` inspect interface is supported) and
|
||||||
|
the following iRMC classic drivers support Hardware Inspection:
|
||||||
|
|
||||||
|
* ``pxe_irmc``
|
||||||
|
* ``iscsi_irmc``
|
||||||
|
* ``agent_irmc``
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
SNMP requires being enabled in ServerView® iRMC S4 Web Server(Network
|
||||||
|
Settings\SNMP section).
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The Hardware Inspection Support in the iRMC drivers requires the following
|
||||||
|
configuration:
|
||||||
|
|
||||||
|
* It is necessary to set ironic configuration with ``gpu_ids`` option
|
||||||
|
in ``[irmc]`` section.
|
||||||
|
|
||||||
|
``gpu_ids`` is a list of ``<vendorID>/<deviceID>`` where:
|
||||||
|
|
||||||
|
- ``<vendorID>``: 4 hexadecimal digits starts with '0x'.
|
||||||
|
- ``<deviceID>``: 4 hexadecimal digits starts with '0x'.
|
||||||
|
|
||||||
|
Here is a sample value for gpu_ids::
|
||||||
|
|
||||||
|
gpu_ids = 0x1000/0x0079,0x2100/0x0080
|
||||||
|
|
||||||
|
* It is necessary that pyghmi version >= 1.0.22 and pysnmp version >= 4.2.3
|
||||||
|
are used on the conductor. The latest version of pyghmi can
|
||||||
|
be downloaded from `here <https://pypi.python.org/pypi/pyghmi/>`__
|
||||||
|
and pysnmp can be downloaded from `here
|
||||||
|
<https://pypi.python.org/pypi/pysnmp/>`__.
|
||||||
|
|
||||||
|
Supported properties
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The inspection process will discover the following essential properties
|
||||||
|
(properties required for scheduling deployment):
|
||||||
|
|
||||||
|
* ``memory_mb``: memory size
|
||||||
|
|
||||||
|
* ``cpus``: number of cpus
|
||||||
|
|
||||||
|
* ``cpu_arch``: cpu architecture
|
||||||
|
|
||||||
|
* ``local_gb``: disk size
|
||||||
|
|
||||||
|
Inspection can also discover the following extra capabilities for iRMC
|
||||||
|
drivers:
|
||||||
|
|
||||||
|
* ``irmc_firmware_version``: iRMC firmware version
|
||||||
|
|
||||||
|
* ``rom_firmware_version``: ROM firmware version
|
||||||
|
|
||||||
|
* ``trusted_boot``: The flag whether TPM(Trusted Platform Module) is
|
||||||
|
supported by the server. The possible values are 'True' or 'False'.
|
||||||
|
|
||||||
|
* ``server_model``: server model
|
||||||
|
|
||||||
|
* ``pci_gpu_devices``: number of gpu devices connected to the bare metal.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
* The disk size is returned only when eLCM License for FUJITSU PRIMERGY
|
||||||
|
servers is activated. If the license is not activated, then Hardware
|
||||||
|
Inspection will fail to get this value.
|
||||||
|
* Before inspecting, if the server is power-off, it will be turned on
|
||||||
|
automatically. System will wait for a few second before start
|
||||||
|
inspecting. After inspection, power status will be restored to the
|
||||||
|
previous state.
|
||||||
|
|
||||||
|
The operator can specify these capabilities in compute service flavor, for
|
||||||
|
example::
|
||||||
|
|
||||||
|
openstack flavor set baremetal-flavor-name --property capabilities:irmc_firmware_version="iRMC S4-8.64F"
|
||||||
|
|
||||||
|
openstack flavor set baremetal-flavor-name --property capabilities:server_model="TX2540M1F5"
|
||||||
|
|
||||||
|
openstack flavor set baremetal-flavor-name --property capabilities:pci_gpu_devices="1"
|
||||||
|
|
||||||
|
See :ref:`capabilities-discovery` 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.4.1
|
||||||
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.5.0
|
python-scciclient>=0.6.0
|
||||||
UcsSdk==0.8.2.2
|
UcsSdk==0.8.2.2
|
||||||
python-dracclient>=1.3.0
|
python-dracclient>=1.3.0
|
||||||
|
|
||||||
|
|
|
@ -1963,6 +1963,15 @@
|
||||||
# value)
|
# value)
|
||||||
#clean_priority_restore_irmc_bios_config = 0
|
#clean_priority_restore_irmc_bios_config = 0
|
||||||
|
|
||||||
|
# List of vendor IDs and device IDs for GPU device to inspect.
|
||||||
|
# List items are in format vendorID/deviceID and separated by
|
||||||
|
# commas. GPU inspection will use this value to count the
|
||||||
|
# number of GPU device in a node. If this option is not
|
||||||
|
# defined, then leave out pci_gpu_devices in capabilities
|
||||||
|
# property. Sample gpu_ids value: 0x1000/0x0079,0x2100/0x0080
|
||||||
|
# (list value)
|
||||||
|
#gpu_ids =
|
||||||
|
|
||||||
|
|
||||||
[ironic_lib]
|
[ironic_lib]
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,15 @@ opts = [
|
||||||
cfg.IntOpt('clean_priority_restore_irmc_bios_config',
|
cfg.IntOpt('clean_priority_restore_irmc_bios_config',
|
||||||
default=0,
|
default=0,
|
||||||
help=_('Priority for restore_irmc_bios_config clean step.')),
|
help=_('Priority for restore_irmc_bios_config clean step.')),
|
||||||
|
cfg.ListOpt('gpu_ids',
|
||||||
|
default=[],
|
||||||
|
help=_('List of vendor IDs and device IDs for GPU device to '
|
||||||
|
'inspect. List items are in format vendorID/deviceID '
|
||||||
|
'and separated by commas. GPU inspection will use this '
|
||||||
|
'value to count the number of GPU device in a node. If '
|
||||||
|
'this option is not defined, then leave out '
|
||||||
|
'pci_gpu_devices in capabilities property. '
|
||||||
|
'Sample gpu_ids value: 0x1000/0x0079,0x2100/0x0080')),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,19 @@
|
||||||
"""
|
"""
|
||||||
iRMC Inspect Interface
|
iRMC Inspect Interface
|
||||||
"""
|
"""
|
||||||
|
import re
|
||||||
|
|
||||||
from ironic_lib import metrics_utils
|
from ironic_lib import metrics_utils
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import importutils
|
from oslo_utils import importutils
|
||||||
|
|
||||||
|
from ironic.common import boot_devices
|
||||||
from ironic.common import exception
|
from ironic.common import exception
|
||||||
from ironic.common.i18n import _
|
from ironic.common.i18n import _
|
||||||
from ironic.common import states
|
from ironic.common import states
|
||||||
|
from ironic.common import utils
|
||||||
|
from ironic.conductor import utils as manager_utils
|
||||||
|
from ironic.conf import CONF
|
||||||
from ironic.drivers import base
|
from ironic.drivers import base
|
||||||
from ironic.drivers.modules.irmc import common as irmc_common
|
from ironic.drivers.modules.irmc import common as irmc_common
|
||||||
from ironic.drivers.modules import snmp
|
from ironic.drivers.modules import snmp
|
||||||
|
@ -84,6 +90,9 @@ sc2UnitNodeMacAddress OBJECT-TYPE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
MAC_ADDRESS_OID = '1.3.6.1.4.1.231.2.10.2.2.10.3.1.1.9.1'
|
MAC_ADDRESS_OID = '1.3.6.1.4.1.231.2.10.2.2.10.3.1.1.9.1'
|
||||||
|
CAPABILITIES_PROPERTIES = {'trusted_boot', 'irmc_firmware_version',
|
||||||
|
'rom_firmware_version', 'server_model',
|
||||||
|
'pci_gpu_devices'}
|
||||||
|
|
||||||
|
|
||||||
def _get_mac_addresses(node):
|
def _get_mac_addresses(node):
|
||||||
|
@ -108,20 +117,55 @@ def _get_mac_addresses(node):
|
||||||
if c == NODE_CLASS_OID_VALUE['primary']]
|
if c == NODE_CLASS_OID_VALUE['primary']]
|
||||||
|
|
||||||
|
|
||||||
def _inspect_hardware(node):
|
def _inspect_hardware(node, **kwargs):
|
||||||
"""Inspect the node and get hardware information.
|
"""Inspect the node and get hardware information.
|
||||||
|
|
||||||
:param node: node object.
|
:param node: node object.
|
||||||
|
:param kwargs: the dictionary of additional parameters.
|
||||||
:raises: HardwareInspectionFailure, if unable to get essential
|
:raises: HardwareInspectionFailure, if unable to get essential
|
||||||
hardware properties.
|
hardware properties.
|
||||||
:returns: a pair of dictionary and list, the dictionary contains
|
:returns: a pair of dictionary and list, the dictionary contains
|
||||||
keys as in IRMCInspect.ESSENTIAL_PROPERTIES and its inspected
|
keys as in IRMCInspect.ESSENTIAL_PROPERTIES and its inspected
|
||||||
values, the list contains mac addresses.
|
values, the list contains mac addresses.
|
||||||
"""
|
"""
|
||||||
|
capabilities_props = set(CAPABILITIES_PROPERTIES)
|
||||||
|
|
||||||
|
# Remove all capabilities item which will be inspected in the existing
|
||||||
|
# capabilities of node
|
||||||
|
if 'capabilities' in node.properties:
|
||||||
|
existing_cap = node.properties['capabilities'].split(',')
|
||||||
|
for item in capabilities_props:
|
||||||
|
for prop in existing_cap:
|
||||||
|
if item == prop.split(':')[0]:
|
||||||
|
existing_cap.remove(prop)
|
||||||
|
node.properties['capabilities'] = ",".join(existing_cap)
|
||||||
|
|
||||||
|
# get gpu_ids in ironic configuration
|
||||||
|
values = [gpu_id.lower() for gpu_id in CONF.irmc.gpu_ids]
|
||||||
|
|
||||||
|
# if gpu_ids = [], pci_gpu_devices will not be inspected
|
||||||
|
if len(values) == 0:
|
||||||
|
capabilities_props.remove('pci_gpu_devices')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
report = irmc_common.get_irmc_report(node)
|
report = irmc_common.get_irmc_report(node)
|
||||||
props = scci.get_essential_properties(
|
props = scci.get_essential_properties(
|
||||||
report, IRMCInspect.ESSENTIAL_PROPERTIES)
|
report, IRMCInspect.ESSENTIAL_PROPERTIES)
|
||||||
|
d_info = irmc_common.parse_driver_info(node)
|
||||||
|
capabilities = scci.get_capabilities_properties(
|
||||||
|
d_info,
|
||||||
|
capabilities_props,
|
||||||
|
values,
|
||||||
|
**kwargs)
|
||||||
|
if capabilities:
|
||||||
|
if capabilities.get('pci_gpu_devices') == 0:
|
||||||
|
capabilities.pop('pci_gpu_devices')
|
||||||
|
if capabilities.get('trusted_boot') is False:
|
||||||
|
capabilities.pop('trusted_boot')
|
||||||
|
capabilities = utils.get_updated_capabilities(
|
||||||
|
node.properties.get('capabilities'), capabilities)
|
||||||
|
if capabilities:
|
||||||
|
props['capabilities'] = capabilities
|
||||||
macs = _get_mac_addresses(node)
|
macs = _get_mac_addresses(node)
|
||||||
except (scci.SCCIInvalidInputError,
|
except (scci.SCCIInvalidInputError,
|
||||||
scci.SCCIClientError,
|
scci.SCCIClientError,
|
||||||
|
@ -137,6 +181,19 @@ def _inspect_hardware(node):
|
||||||
class IRMCInspect(base.InspectInterface):
|
class IRMCInspect(base.InspectInterface):
|
||||||
"""Interface for out of band inspection."""
|
"""Interface for out of band inspection."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""Validate the driver-specific inspection information.
|
||||||
|
|
||||||
|
This action will validate gpu_ids value along with starting
|
||||||
|
ironic-conductor service.
|
||||||
|
"""
|
||||||
|
for gpu_id in CONF.irmc.gpu_ids:
|
||||||
|
if not re.match('^0x[0-9a-f]{4}/0x[0-9a-f]{4}$', gpu_id.lower()):
|
||||||
|
raise exception.InvalidParameterValue(_(
|
||||||
|
"Invalid [irmc]/gpu_ids configuration option."))
|
||||||
|
|
||||||
|
super(IRMCInspect, self).__init__()
|
||||||
|
|
||||||
def get_properties(self):
|
def get_properties(self):
|
||||||
"""Return the properties of the interface.
|
"""Return the properties of the interface.
|
||||||
|
|
||||||
|
@ -170,7 +227,20 @@ class IRMCInspect(base.InspectInterface):
|
||||||
:returns: states.MANAGEABLE, if hardware inspection succeeded.
|
:returns: states.MANAGEABLE, if hardware inspection succeeded.
|
||||||
"""
|
"""
|
||||||
node = task.node
|
node = task.node
|
||||||
(props, macs) = _inspect_hardware(node)
|
kwargs = {}
|
||||||
|
# Inspect additional capabilities task requires node with power on
|
||||||
|
# status
|
||||||
|
old_power_state = task.driver.power.get_power_state(task)
|
||||||
|
if old_power_state == states.POWER_OFF:
|
||||||
|
manager_utils.node_set_boot_device(task, boot_devices.BIOS, False)
|
||||||
|
manager_utils.node_power_action(task, states.POWER_ON)
|
||||||
|
|
||||||
|
LOG.info("The Node %(node_uuid)s being powered on for inspection",
|
||||||
|
{'node_uuid': task.node.uuid})
|
||||||
|
|
||||||
|
kwargs['sleep_flag'] = True
|
||||||
|
|
||||||
|
(props, macs) = _inspect_hardware(node, **kwargs)
|
||||||
node.properties = dict(node.properties, **props)
|
node.properties = dict(node.properties, **props)
|
||||||
node.save()
|
node.save()
|
||||||
|
|
||||||
|
@ -189,4 +259,12 @@ class IRMCInspect(base.InspectInterface):
|
||||||
{'address': mac, 'node_uuid': node.uuid})
|
{'address': mac, 'node_uuid': node.uuid})
|
||||||
|
|
||||||
LOG.info("Node %s inspected", node.uuid)
|
LOG.info("Node %s inspected", node.uuid)
|
||||||
|
# restore old power state
|
||||||
|
if old_power_state == states.POWER_OFF:
|
||||||
|
manager_utils.node_power_action(task, states.POWER_OFF)
|
||||||
|
|
||||||
|
LOG.info("The Node %(node_uuid)s being powered off after "
|
||||||
|
"inspection",
|
||||||
|
{'node_uuid': task.node.uuid})
|
||||||
|
|
||||||
return states.MANAGEABLE
|
return states.MANAGEABLE
|
||||||
|
|
|
@ -20,15 +20,19 @@ import mock
|
||||||
|
|
||||||
from ironic.common import exception
|
from ironic.common import exception
|
||||||
from ironic.common import states
|
from ironic.common import states
|
||||||
|
from ironic.common import utils
|
||||||
from ironic.conductor import task_manager
|
from ironic.conductor import task_manager
|
||||||
|
from ironic.conductor import utils as manager_utils
|
||||||
from ironic.drivers.modules.irmc import common as irmc_common
|
from ironic.drivers.modules.irmc import common as irmc_common
|
||||||
from ironic.drivers.modules.irmc import inspect as irmc_inspect
|
from ironic.drivers.modules.irmc import inspect as irmc_inspect
|
||||||
|
from ironic.drivers.modules.irmc import power as irmc_power
|
||||||
from ironic import objects
|
from ironic import objects
|
||||||
from ironic.tests.unit.conductor import mgr_utils
|
from ironic.tests.unit.conductor import mgr_utils
|
||||||
from ironic.tests.unit.db import base as db_base
|
from ironic.tests.unit.db import base as db_base
|
||||||
from ironic.tests.unit.db import utils as db_utils
|
from ironic.tests.unit.db import utils as db_utils
|
||||||
from ironic.tests.unit.drivers import third_party_driver_mock_specs \
|
from ironic.tests.unit.drivers import (
|
||||||
as mock_specs
|
third_party_driver_mock_specs as mock_specs
|
||||||
|
)
|
||||||
from ironic.tests.unit.objects import utils as obj_utils
|
from ironic.tests.unit.objects import utils as obj_utils
|
||||||
|
|
||||||
INFO_DICT = db_utils.get_test_irmc_info()
|
INFO_DICT = db_utils.get_test_irmc_info()
|
||||||
|
@ -66,24 +70,45 @@ class IRMCInspectInternalMethodsTestCase(db_base.DbTestCase):
|
||||||
autospec=True)
|
autospec=True)
|
||||||
def test__inspect_hardware(
|
def test__inspect_hardware(
|
||||||
self, get_irmc_report_mock, scci_mock, _get_mac_addresses_mock):
|
self, get_irmc_report_mock, scci_mock, _get_mac_addresses_mock):
|
||||||
|
# Set config flags
|
||||||
|
gpu_ids = ['0x1000/0x0079', '0x2100/0x0080']
|
||||||
|
|
||||||
|
self.config(gpu_ids=gpu_ids, group='irmc')
|
||||||
|
kwargs = {'sleep_flag': False}
|
||||||
|
|
||||||
inspected_props = {
|
inspected_props = {
|
||||||
'memory_mb': '1024',
|
'memory_mb': '1024',
|
||||||
'local_gb': 10,
|
'local_gb': 10,
|
||||||
'cpus': 2,
|
'cpus': 2,
|
||||||
'cpu_arch': 'x86_64'}
|
'cpu_arch': 'x86_64'}
|
||||||
|
inspected_capabilities = {
|
||||||
|
'trusted_boot': False,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x',
|
||||||
|
'pci_gpu_devices': 1}
|
||||||
|
|
||||||
inspected_macs = ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb']
|
inspected_macs = ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb']
|
||||||
report = 'fake_report'
|
report = 'fake_report'
|
||||||
get_irmc_report_mock.return_value = report
|
get_irmc_report_mock.return_value = report
|
||||||
scci_mock.get_essential_properties.return_value = inspected_props
|
scci_mock.get_essential_properties.return_value = inspected_props
|
||||||
|
scci_mock.get_capabilities_properties.return_value = (
|
||||||
|
inspected_capabilities)
|
||||||
_get_mac_addresses_mock.return_value = inspected_macs
|
_get_mac_addresses_mock.return_value = inspected_macs
|
||||||
with task_manager.acquire(self.context, self.node.uuid,
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
shared=True) as task:
|
shared=True) as task:
|
||||||
result = irmc_inspect._inspect_hardware(task.node)
|
result = irmc_inspect._inspect_hardware(task.node, **kwargs)
|
||||||
|
|
||||||
get_irmc_report_mock.assert_called_once_with(task.node)
|
get_irmc_report_mock.assert_called_once_with(task.node)
|
||||||
scci_mock.get_essential_properties.assert_called_once_with(
|
scci_mock.get_essential_properties.assert_called_once_with(
|
||||||
report, irmc_inspect.IRMCInspect.ESSENTIAL_PROPERTIES)
|
report, irmc_inspect.IRMCInspect.ESSENTIAL_PROPERTIES)
|
||||||
self.assertEqual((inspected_props, inspected_macs), result)
|
scci_mock.get_capabilities_properties.assert_called_once_with(
|
||||||
|
mock.ANY, irmc_inspect.CAPABILITIES_PROPERTIES,
|
||||||
|
gpu_ids, **kwargs)
|
||||||
|
expected_props = dict(inspected_props)
|
||||||
|
inspected_capabilities = utils.get_updated_capabilities(
|
||||||
|
'', inspected_capabilities)
|
||||||
|
expected_props['capabilities'] = inspected_capabilities
|
||||||
|
self.assertEqual((expected_props, inspected_macs), result)
|
||||||
|
|
||||||
@mock.patch.object(irmc_inspect, '_get_mac_addresses', spec_set=True,
|
@mock.patch.object(irmc_inspect, '_get_mac_addresses', spec_set=True,
|
||||||
autospec=True)
|
autospec=True)
|
||||||
|
@ -94,6 +119,7 @@ class IRMCInspectInternalMethodsTestCase(db_base.DbTestCase):
|
||||||
def test__inspect_hardware_exception(
|
def test__inspect_hardware_exception(
|
||||||
self, get_irmc_report_mock, scci_mock, _get_mac_addresses_mock):
|
self, get_irmc_report_mock, scci_mock, _get_mac_addresses_mock):
|
||||||
report = 'fake_report'
|
report = 'fake_report'
|
||||||
|
kwargs = {'sleep_flag': False}
|
||||||
get_irmc_report_mock.return_value = report
|
get_irmc_report_mock.return_value = report
|
||||||
side_effect = exception.SNMPFailure("fake exception")
|
side_effect = exception.SNMPFailure("fake exception")
|
||||||
scci_mock.get_essential_properties.side_effect = side_effect
|
scci_mock.get_essential_properties.side_effect = side_effect
|
||||||
|
@ -104,7 +130,7 @@ class IRMCInspectInternalMethodsTestCase(db_base.DbTestCase):
|
||||||
shared=True) as task:
|
shared=True) as task:
|
||||||
self.assertRaises(exception.HardwareInspectionFailure,
|
self.assertRaises(exception.HardwareInspectionFailure,
|
||||||
irmc_inspect._inspect_hardware,
|
irmc_inspect._inspect_hardware,
|
||||||
task.node)
|
task.node, **kwargs)
|
||||||
get_irmc_report_mock.assert_called_once_with(task.node)
|
get_irmc_report_mock.assert_called_once_with(task.node)
|
||||||
self.assertFalse(_get_mac_addresses_mock.called)
|
self.assertFalse(_get_mac_addresses_mock.called)
|
||||||
|
|
||||||
|
@ -131,7 +157,7 @@ class IRMCInspectTestCase(db_base.DbTestCase):
|
||||||
def test_validate(self, parse_driver_info_mock):
|
def test_validate(self, parse_driver_info_mock):
|
||||||
with task_manager.acquire(self.context, self.node.uuid,
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
shared=True) as task:
|
shared=True) as task:
|
||||||
task.driver.power.validate(task)
|
task.driver.inspect.validate(task)
|
||||||
parse_driver_info_mock.assert_called_once_with(task.node)
|
parse_driver_info_mock.assert_called_once_with(task.node)
|
||||||
|
|
||||||
@mock.patch.object(irmc_common, 'parse_driver_info', spec_set=True,
|
@mock.patch.object(irmc_common, 'parse_driver_info', spec_set=True,
|
||||||
|
@ -143,22 +169,31 @@ class IRMCInspectTestCase(db_base.DbTestCase):
|
||||||
with task_manager.acquire(self.context, self.node.uuid,
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
shared=True) as task:
|
shared=True) as task:
|
||||||
self.assertRaises(exception.InvalidParameterValue,
|
self.assertRaises(exception.InvalidParameterValue,
|
||||||
task.driver.power.validate,
|
task.driver.inspect.validate,
|
||||||
task)
|
task)
|
||||||
|
|
||||||
|
def test__init_fail_invalid_input(self):
|
||||||
|
# Set config flags
|
||||||
|
self.config(gpu_ids='100/x079,0x20/', group='irmc')
|
||||||
|
self.assertRaises(exception.InvalidParameterValue,
|
||||||
|
irmc_inspect.IRMCInspect)
|
||||||
|
|
||||||
@mock.patch.object(irmc_inspect.LOG, 'info', spec_set=True, autospec=True)
|
@mock.patch.object(irmc_inspect.LOG, 'info', spec_set=True, autospec=True)
|
||||||
@mock.patch('ironic.drivers.modules.irmc.inspect.objects.Port',
|
@mock.patch('ironic.drivers.modules.irmc.inspect.objects.Port',
|
||||||
spec_set=True, autospec=True)
|
spec_set=True, autospec=True)
|
||||||
@mock.patch.object(irmc_inspect, '_inspect_hardware', spec_set=True,
|
@mock.patch.object(irmc_inspect, '_inspect_hardware', spec_set=True,
|
||||||
autospec=True)
|
autospec=True)
|
||||||
def test_inspect_hardware(self, _inspect_hardware_mock, port_mock,
|
@mock.patch.object(irmc_power.IRMCPower, 'get_power_state', spec_set=True,
|
||||||
info_mock):
|
autospec=True)
|
||||||
|
def test_inspect_hardware(self, power_state_mock, _inspect_hardware_mock,
|
||||||
|
port_mock, info_mock):
|
||||||
inspected_props = {
|
inspected_props = {
|
||||||
'memory_mb': '1024',
|
'memory_mb': '1024',
|
||||||
'local_gb': 10,
|
'local_gb': 10,
|
||||||
'cpus': 2,
|
'cpus': 2,
|
||||||
'cpu_arch': 'x86_64'}
|
'cpu_arch': 'x86_64'}
|
||||||
inspected_macs = ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb']
|
inspected_macs = ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb']
|
||||||
|
power_state_mock.return_value = states.POWER_ON
|
||||||
_inspect_hardware_mock.return_value = (inspected_props,
|
_inspect_hardware_mock.return_value = (inspected_props,
|
||||||
inspected_macs)
|
inspected_macs)
|
||||||
new_port_mock1 = mock.MagicMock(spec=objects.Port)
|
new_port_mock1 = mock.MagicMock(spec=objects.Port)
|
||||||
|
@ -167,7 +202,7 @@ class IRMCInspectTestCase(db_base.DbTestCase):
|
||||||
port_mock.side_effect = [new_port_mock1, new_port_mock2]
|
port_mock.side_effect = [new_port_mock1, new_port_mock2]
|
||||||
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid,
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
shared=True) as task:
|
shared=False) as task:
|
||||||
result = task.driver.inspect.inspect_hardware(task)
|
result = task.driver.inspect.inspect_hardware(task)
|
||||||
|
|
||||||
node_id = task.node.id
|
node_id = task.node.id
|
||||||
|
@ -204,16 +239,73 @@ class IRMCInspectTestCase(db_base.DbTestCase):
|
||||||
self.assertEqual(inspected_props, task.node.properties)
|
self.assertEqual(inspected_props, task.node.properties)
|
||||||
self.assertEqual(states.MANAGEABLE, result)
|
self.assertEqual(states.MANAGEABLE, result)
|
||||||
|
|
||||||
|
@mock.patch.object(manager_utils, 'node_power_action', spec_set=True,
|
||||||
|
autospec=True)
|
||||||
|
@mock.patch.object(manager_utils, 'node_set_boot_device', spec_set=True,
|
||||||
|
autospec=True)
|
||||||
|
@mock.patch.object(irmc_inspect.LOG, 'info', spec_set=True, autospec=True)
|
||||||
|
@mock.patch.object(irmc_inspect.objects, 'Port',
|
||||||
|
spec_set=True, autospec=True)
|
||||||
|
@mock.patch.object(irmc_inspect, '_inspect_hardware', spec_set=True,
|
||||||
|
autospec=True)
|
||||||
|
@mock.patch.object(irmc_power.IRMCPower, 'get_power_state', spec_set=True,
|
||||||
|
autospec=True)
|
||||||
|
def test_inspect_hardware_with_power_off(self, power_state_mock,
|
||||||
|
_inspect_hardware_mock,
|
||||||
|
port_mock, info_mock,
|
||||||
|
set_boot_device_mock,
|
||||||
|
power_action_mock):
|
||||||
|
inspected_props = {
|
||||||
|
'memory_mb': '1024',
|
||||||
|
'local_gb': 10,
|
||||||
|
'cpus': 2,
|
||||||
|
'cpu_arch': 'x86_64'}
|
||||||
|
inspected_macs = ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb']
|
||||||
|
power_state_mock.return_value = states.POWER_OFF
|
||||||
|
_inspect_hardware_mock.return_value = (inspected_props,
|
||||||
|
inspected_macs)
|
||||||
|
new_port_mock1 = mock.MagicMock(spec=objects.Port)
|
||||||
|
new_port_mock2 = mock.MagicMock(spec=objects.Port)
|
||||||
|
|
||||||
|
port_mock.side_effect = [new_port_mock1, new_port_mock2]
|
||||||
|
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=False) as task:
|
||||||
|
result = task.driver.inspect.inspect_hardware(task)
|
||||||
|
|
||||||
|
node_id = task.node.id
|
||||||
|
_inspect_hardware_mock.assert_called_once_with(task.node,
|
||||||
|
sleep_flag=True)
|
||||||
|
|
||||||
|
port_mock.assert_has_calls([
|
||||||
|
mock.call(task.context, address=inspected_macs[0],
|
||||||
|
node_id=node_id),
|
||||||
|
mock.call(task.context, address=inspected_macs[1],
|
||||||
|
node_id=node_id)
|
||||||
|
])
|
||||||
|
new_port_mock1.create.assert_called_once_with()
|
||||||
|
new_port_mock2.create.assert_called_once_with()
|
||||||
|
|
||||||
|
self.assertTrue(info_mock.called)
|
||||||
|
task.node.refresh()
|
||||||
|
self.assertEqual(inspected_props, task.node.properties)
|
||||||
|
self.assertEqual(states.MANAGEABLE, result)
|
||||||
|
self.assertEqual(power_action_mock.called, True)
|
||||||
|
self.assertEqual(power_action_mock.call_count, 2)
|
||||||
|
|
||||||
@mock.patch('ironic.objects.Port', spec_set=True, autospec=True)
|
@mock.patch('ironic.objects.Port', spec_set=True, autospec=True)
|
||||||
@mock.patch.object(irmc_inspect, '_inspect_hardware', spec_set=True,
|
@mock.patch.object(irmc_inspect, '_inspect_hardware', spec_set=True,
|
||||||
autospec=True)
|
autospec=True)
|
||||||
|
@mock.patch.object(irmc_power.IRMCPower, 'get_power_state', spec_set=True,
|
||||||
|
autospec=True)
|
||||||
def test_inspect_hardware_inspect_exception(
|
def test_inspect_hardware_inspect_exception(
|
||||||
self, _inspect_hardware_mock, port_mock):
|
self, power_state_mock, _inspect_hardware_mock, port_mock):
|
||||||
side_effect = exception.HardwareInspectionFailure("fake exception")
|
side_effect = exception.HardwareInspectionFailure("fake exception")
|
||||||
_inspect_hardware_mock.side_effect = side_effect
|
_inspect_hardware_mock.side_effect = side_effect
|
||||||
|
power_state_mock.return_value = states.POWER_ON
|
||||||
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid,
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
shared=True) as task:
|
shared=False) as task:
|
||||||
self.assertRaises(exception.HardwareInspectionFailure,
|
self.assertRaises(exception.HardwareInspectionFailure,
|
||||||
task.driver.inspect.inspect_hardware,
|
task.driver.inspect.inspect_hardware,
|
||||||
task)
|
task)
|
||||||
|
@ -223,8 +315,11 @@ class IRMCInspectTestCase(db_base.DbTestCase):
|
||||||
@mock.patch('ironic.objects.Port', spec_set=True, autospec=True)
|
@mock.patch('ironic.objects.Port', spec_set=True, autospec=True)
|
||||||
@mock.patch.object(irmc_inspect, '_inspect_hardware', spec_set=True,
|
@mock.patch.object(irmc_inspect, '_inspect_hardware', spec_set=True,
|
||||||
autospec=True)
|
autospec=True)
|
||||||
|
@mock.patch.object(irmc_power.IRMCPower, 'get_power_state', spec_set=True,
|
||||||
|
autospec=True)
|
||||||
def test_inspect_hardware_mac_already_exist(
|
def test_inspect_hardware_mac_already_exist(
|
||||||
self, _inspect_hardware_mock, port_mock, warn_mock):
|
self, power_state_mock, _inspect_hardware_mock,
|
||||||
|
port_mock, warn_mock):
|
||||||
inspected_props = {
|
inspected_props = {
|
||||||
'memory_mb': '1024',
|
'memory_mb': '1024',
|
||||||
'local_gb': 10,
|
'local_gb': 10,
|
||||||
|
@ -233,12 +328,13 @@ class IRMCInspectTestCase(db_base.DbTestCase):
|
||||||
inspected_macs = ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb']
|
inspected_macs = ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb']
|
||||||
_inspect_hardware_mock.return_value = (inspected_props,
|
_inspect_hardware_mock.return_value = (inspected_props,
|
||||||
inspected_macs)
|
inspected_macs)
|
||||||
|
power_state_mock.return_value = states.POWER_ON
|
||||||
side_effect = exception.MACAlreadyExists("fake exception")
|
side_effect = exception.MACAlreadyExists("fake exception")
|
||||||
new_port_mock = port_mock.return_value
|
new_port_mock = port_mock.return_value
|
||||||
new_port_mock.create.side_effect = side_effect
|
new_port_mock.create.side_effect = side_effect
|
||||||
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid,
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
shared=True) as task:
|
shared=False) as task:
|
||||||
result = task.driver.inspect.inspect_hardware(task)
|
result = task.driver.inspect.inspect_hardware(task)
|
||||||
|
|
||||||
_inspect_hardware_mock.assert_called_once_with(task.node)
|
_inspect_hardware_mock.assert_called_once_with(task.node)
|
||||||
|
@ -246,3 +342,225 @@ class IRMCInspectTestCase(db_base.DbTestCase):
|
||||||
task.node.refresh()
|
task.node.refresh()
|
||||||
self.assertEqual(inspected_props, task.node.properties)
|
self.assertEqual(inspected_props, task.node.properties)
|
||||||
self.assertEqual(states.MANAGEABLE, result)
|
self.assertEqual(states.MANAGEABLE, result)
|
||||||
|
|
||||||
|
@mock.patch.object(irmc_inspect, '_get_mac_addresses', spec_set=True,
|
||||||
|
autospec=True)
|
||||||
|
@mock.patch.object(irmc_inspect, 'scci',
|
||||||
|
spec_set=mock_specs.SCCICLIENT_IRMC_SCCI_SPEC)
|
||||||
|
@mock.patch.object(irmc_common, 'get_irmc_report', spec_set=True,
|
||||||
|
autospec=True)
|
||||||
|
def _test_inspect_hardware_props(self, gpu_ids,
|
||||||
|
existed_capabilities,
|
||||||
|
inspected_capabilities,
|
||||||
|
expected_capabilities,
|
||||||
|
get_irmc_report_mock,
|
||||||
|
scci_mock,
|
||||||
|
_get_mac_addresses_mock):
|
||||||
|
capabilities_props = set(irmc_inspect.CAPABILITIES_PROPERTIES)
|
||||||
|
|
||||||
|
# if gpu_ids = [], pci_gpu_devices will not be inspected
|
||||||
|
if len(gpu_ids) == 0:
|
||||||
|
capabilities_props.remove('pci_gpu_devices')
|
||||||
|
|
||||||
|
self.config(gpu_ids=gpu_ids, group='irmc')
|
||||||
|
kwargs = {'sleep_flag': False}
|
||||||
|
|
||||||
|
inspected_props = {
|
||||||
|
'memory_mb': '1024',
|
||||||
|
'local_gb': 10,
|
||||||
|
'cpus': 2,
|
||||||
|
'cpu_arch': 'x86_64'}
|
||||||
|
|
||||||
|
inspected_macs = ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb']
|
||||||
|
report = 'fake_report'
|
||||||
|
get_irmc_report_mock.return_value = report
|
||||||
|
scci_mock.get_essential_properties.return_value = inspected_props
|
||||||
|
scci_mock.get_capabilities_properties.return_value = \
|
||||||
|
inspected_capabilities
|
||||||
|
_get_mac_addresses_mock.return_value = inspected_macs
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
task.node.properties[u'capabilities'] =\
|
||||||
|
",".join('%(k)s:%(v)s' % {'k': k, 'v': v}
|
||||||
|
for k, v in existed_capabilities.items())
|
||||||
|
result = irmc_inspect._inspect_hardware(task.node, **kwargs)
|
||||||
|
get_irmc_report_mock.assert_called_once_with(task.node)
|
||||||
|
scci_mock.get_essential_properties.assert_called_once_with(
|
||||||
|
report, irmc_inspect.IRMCInspect.ESSENTIAL_PROPERTIES)
|
||||||
|
scci_mock.get_capabilities_properties.assert_called_once_with(
|
||||||
|
mock.ANY, capabilities_props,
|
||||||
|
gpu_ids, **kwargs)
|
||||||
|
expected_capabilities = utils.get_updated_capabilities(
|
||||||
|
'', expected_capabilities)
|
||||||
|
|
||||||
|
set1 = set(expected_capabilities.split(','))
|
||||||
|
set2 = set(result[0]['capabilities'].split(','))
|
||||||
|
self.assertEqual(set1, set2)
|
||||||
|
|
||||||
|
def test_inspect_hardware_existing_cap_in_props(self):
|
||||||
|
# Set config flags
|
||||||
|
gpu_ids = ['0x1000/0x0079', '0x2100/0x0080']
|
||||||
|
existed_capabilities = {
|
||||||
|
'trusted_boot': True,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x',
|
||||||
|
'pci_gpu_devices': 1}
|
||||||
|
inspected_capabilities = {
|
||||||
|
'trusted_boot': True,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x',
|
||||||
|
'pci_gpu_devices': 1}
|
||||||
|
expected_capabilities = {
|
||||||
|
'trusted_boot': True,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x',
|
||||||
|
'pci_gpu_devices': 1}
|
||||||
|
|
||||||
|
self._test_inspect_hardware_props(gpu_ids,
|
||||||
|
existed_capabilities,
|
||||||
|
inspected_capabilities,
|
||||||
|
expected_capabilities)
|
||||||
|
|
||||||
|
def test_inspect_hardware_props_empty_gpu_ids(self):
|
||||||
|
# Set config flags
|
||||||
|
gpu_ids = []
|
||||||
|
existed_capabilities = {}
|
||||||
|
inspected_capabilities = {
|
||||||
|
'trusted_boot': True,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x'}
|
||||||
|
expected_capabilities = {
|
||||||
|
'trusted_boot': True,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x'}
|
||||||
|
|
||||||
|
self._test_inspect_hardware_props(gpu_ids,
|
||||||
|
existed_capabilities,
|
||||||
|
inspected_capabilities,
|
||||||
|
expected_capabilities)
|
||||||
|
|
||||||
|
def test_inspect_hardware_props_pci_gpu_devices_return_zero(self):
|
||||||
|
# Set config flags
|
||||||
|
gpu_ids = ['0x1000/0x0079', '0x2100/0x0080']
|
||||||
|
|
||||||
|
existed_capabilities = {}
|
||||||
|
inspected_capabilities = {
|
||||||
|
'trusted_boot': True,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x',
|
||||||
|
'pci_gpu_devices': 0}
|
||||||
|
expected_capabilities = {
|
||||||
|
'trusted_boot': True,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x'}
|
||||||
|
|
||||||
|
self._test_inspect_hardware_props(gpu_ids,
|
||||||
|
existed_capabilities,
|
||||||
|
inspected_capabilities,
|
||||||
|
expected_capabilities)
|
||||||
|
|
||||||
|
def test_inspect_hardware_props_empty_gpu_ids_and_existing_cap(self):
|
||||||
|
# Set config flags
|
||||||
|
gpu_ids = []
|
||||||
|
existed_capabilities = {
|
||||||
|
'trusted_boot': True,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x',
|
||||||
|
'pci_gpu_devices': 1}
|
||||||
|
inspected_capabilities = {
|
||||||
|
'trusted_boot': True,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x'}
|
||||||
|
expected_capabilities = {
|
||||||
|
'trusted_boot': True,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x'}
|
||||||
|
|
||||||
|
self._test_inspect_hardware_props(gpu_ids,
|
||||||
|
existed_capabilities,
|
||||||
|
inspected_capabilities,
|
||||||
|
expected_capabilities)
|
||||||
|
|
||||||
|
def test_inspect_hardware_props_pci_gpu_devices_zero_and_existing_cap(
|
||||||
|
self):
|
||||||
|
# Set config flags
|
||||||
|
gpu_ids = ['0x1000/0x0079', '0x2100/0x0080']
|
||||||
|
existed_capabilities = {
|
||||||
|
'trusted_boot': True,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x',
|
||||||
|
'pci_gpu_devices': 1}
|
||||||
|
inspected_capabilities = {
|
||||||
|
'trusted_boot': True,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x',
|
||||||
|
'pci_gpu_devices': 0}
|
||||||
|
expected_capabilities = {
|
||||||
|
'trusted_boot': True,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x'}
|
||||||
|
|
||||||
|
self._test_inspect_hardware_props(gpu_ids,
|
||||||
|
existed_capabilities,
|
||||||
|
inspected_capabilities,
|
||||||
|
expected_capabilities)
|
||||||
|
|
||||||
|
def test_inspect_hardware_props_trusted_boot_is_false(self):
|
||||||
|
# Set config flags
|
||||||
|
gpu_ids = ['0x1000/0x0079', '0x2100/0x0080']
|
||||||
|
existed_capabilities = {}
|
||||||
|
inspected_capabilities = {
|
||||||
|
'trusted_boot': False,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x',
|
||||||
|
'pci_gpu_devices': 1}
|
||||||
|
expected_capabilities = {
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x',
|
||||||
|
'pci_gpu_devices': 1}
|
||||||
|
|
||||||
|
self._test_inspect_hardware_props(gpu_ids,
|
||||||
|
existed_capabilities,
|
||||||
|
inspected_capabilities,
|
||||||
|
expected_capabilities)
|
||||||
|
|
||||||
|
def test_inspect_hardware_props_trusted_boot_is_false_and_existing_cap(
|
||||||
|
self):
|
||||||
|
# Set config flags
|
||||||
|
gpu_ids = ['0x1000/0x0079', '0x2100/0x0080']
|
||||||
|
existed_capabilities = {
|
||||||
|
'trusted_boot': True,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x',
|
||||||
|
'pci_gpu_devices': 1}
|
||||||
|
inspected_capabilities = {
|
||||||
|
'trusted_boot': False,
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x',
|
||||||
|
'pci_gpu_devices': 1}
|
||||||
|
expected_capabilities = {
|
||||||
|
'irmc_firmware_version': 'iRMC S4-7.82F',
|
||||||
|
'server_model': 'TX2540M1F5',
|
||||||
|
'rom_firmware_version': 'V4.6.5.4 R1.15.0 for D3099-B1x',
|
||||||
|
'pci_gpu_devices': 1}
|
||||||
|
self._test_inspect_hardware_props(gpu_ids,
|
||||||
|
existed_capabilities,
|
||||||
|
inspected_capabilities,
|
||||||
|
expected_capabilities)
|
||||||
|
|
|
@ -102,6 +102,7 @@ SCCICLIENT_IRMC_SCCI_SPEC = (
|
||||||
'get_virtual_cd_set_params_cmd',
|
'get_virtual_cd_set_params_cmd',
|
||||||
'get_virtual_fd_set_params_cmd',
|
'get_virtual_fd_set_params_cmd',
|
||||||
'get_essential_properties',
|
'get_essential_properties',
|
||||||
|
'get_capabilities_properties',
|
||||||
)
|
)
|
||||||
SCCICLIENT_IRMC_ELCM_SPEC = (
|
SCCICLIENT_IRMC_ELCM_SPEC = (
|
||||||
'backup_bios_config',
|
'backup_bios_config',
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Adds new capabilities ("server_model", "rom_firmware_version", "pci_gpu_devices",
|
||||||
|
"trusted_boot" and "irmc_firmware_version") to the iRMC out-of-band hardware inspection
|
||||||
|
for FUJITSU PRIMERGY bare metal nodes with firmware iRMC S4 and beyond.
|
||||||
|
Before inspecting, if a server is power-off, it will be turned on automatically.
|
||||||
|
System will wait for a few second before start inspecting. After inspection,
|
||||||
|
power status will be restored to the previous state.
|
Loading…
Reference in New Issue