Enables event subscription methods for ilo and ilo5 hardware types

Enables event subscription methods by inheriting RedfishVendorPassthru
for ilo and ilo5 hardware types

Story: 2010207
Task: 45931
Change-Id: I96f7e44069402e3f1d25bcd527408008ca5e77cb
This commit is contained in:
mallikarjuna.kolagatla 2022-08-17 13:01:58 +00:00
parent 4a347b3069
commit 166bd1697a
8 changed files with 178 additions and 5 deletions

View File

@ -65,6 +65,7 @@ The hardware type ``ilo`` supports following HPE server features:
* `BIOS configuration support`_
* `IPv6 support`_
* `Layer 3 or DHCP-less ramdisk booting`_
* `Events subscription`_
Apart from above features hardware type ``ilo5`` also supports following
features:
@ -200,6 +201,18 @@ The ``ilo`` hardware type supports following hardware interfaces:
enabled_hardware_types = ilo
enabled_rescue_interfaces = agent,no-rescue
* vendor
Supports ``ilo``, ``ilo-redfish`` and ``no-vendor``. The default is
``ilo``. They can be enabled by using the
``[DEFAULT]enabled_vendor_interfaces`` option in ``ironic.conf`` as given
below:
.. code-block:: ini
[DEFAULT]
enabled_hardware_types = ilo
enabled_vendor_interfaces = ilo,ilo-redfish,no-vendor
The ``ilo5`` hardware type supports all the ``ilo`` interfaces described above,
except for ``boot`` and ``raid`` interfaces. The details of ``boot`` and
@ -2136,6 +2149,12 @@ DHCP-less deploy is supported by ``ilo`` and ``ilo5`` hardware types.
However it would work only with ilo-virtual-media boot interface. See
:doc:`/admin/dhcp-less` for more information.
Events subscription
^^^^^^^^^^^^^^^^^^^
Events subscription is supported by ``ilo`` and ``ilo5`` hardware types with
``ilo`` vendor interface for Gen10 and Gen10 Plus servers. See
:ref:`node-vendor-passthru-methods` for more information.
.. _`ssacli documentation`: https://support.hpe.com/hpsc/doc/public/display?docId=c03909334
.. _`proliant-tools`: https://docs.openstack.org/diskimage-builder/latest/elements/proliant-tools/README.html
.. _`HPE iLO4 User Guide`: https://h20566.www2.hpe.com/hpsc/doc/public/display?docId=c03334051

View File

@ -533,6 +533,8 @@ settings. The following fields will be returned in the BIOS API
"``unique``", "The setting is specific to this node"
"``reset_required``", "After changing this setting a node reboot is required"
.. _node-vendor-passthru-methods:
Node Vendor Passthru Methods
============================

View File

@ -1,3 +1,4 @@
# Copyright 2022 Hewlett Packard Enterprise Development LP
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -67,7 +68,7 @@ class IloHardware(generic.GenericHardware):
@property
def supported_vendor_interfaces(self):
"""List of supported power interfaces."""
"""List of supported vendor interfaces."""
return [vendor.VendorPassthru, noop.NoVendor]

View File

@ -1,3 +1,4 @@
# Copyright 2022 Hewlett Packard Enterprise Development LP
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -494,6 +495,26 @@ def update_ipmi_properties(task):
task.node.driver_info = info
def update_redfish_properties(task):
"""Update redfish properties to node driver_info
This method updates the node's driver info with redfish driver driver_info.
:param task: a task from TaskManager.
"""
node = task.node
info = node.driver_info
# updating redfish credentials
info['redfish_address'] = info.get('ilo_address')
info['redfish_username'] = info.get('ilo_username')
info['redfish_password'] = info.get('ilo_password')
info['redfish_verify_ca'] = info.get('ilo_verify_ca')
info['redfish_system_id'] = '/redfish/v1/Systems/1'
# saving redfish credentials to task object
task.node.driver_info = info
def _get_floppy_image_name(node):
"""Returns the floppy image name for a given node.

View File

@ -1,3 +1,4 @@
# Copyright 2022 Hewlett Packard Enterprise Development LP
# Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -25,16 +26,14 @@ from ironic.conductor import utils as manager_utils
from ironic.drivers import base
from ironic.drivers.modules import deploy_utils
from ironic.drivers.modules.ilo import common as ilo_common
from ironic.drivers.modules.redfish import vendor as redfish_vendor
METRICS = metrics_utils.get_metrics_logger(__name__)
class VendorPassthru(base.VendorInterface):
class VendorPassthru(redfish_vendor.RedfishVendorPassthru):
"""Vendor-specific interfaces for iLO deploy drivers."""
def get_properties(self):
return {}
@METRICS.timer('IloVendorPassthru.validate')
def validate(self, task, method, **kwargs):
"""Validate vendor-specific actions.
@ -50,10 +49,26 @@ class VendorPassthru(base.VendorInterface):
passed.
:raises: InvalidParameterValue, if any of the parameters have invalid
value.
:raises: IloOperationNotSupported, if the driver does not support the
given operation with ilo vendor interface.
"""
if method == 'boot_into_iso':
self._validate_boot_into_iso(task, kwargs)
return
redfish_event_methods = ['create_subscription',
'delete_subscription',
'get_all_subscriptions', 'get_subscription']
if method in redfish_event_methods:
self._validate_is_it_a_supported_system(task)
ilo_common.parse_driver_info(task.node)
ilo_common.update_redfish_properties(task)
if method == 'eject_vmedia':
error_message = _(method + (
" can not be performed as the driver does not support "
"eject_vmedia through ilo vendor interface"))
raise exception.IloOperationNotSupported(operation=method,
error=error_message)
super(VendorPassthru, self).validate(task, method, **kwargs)
def _validate_boot_into_iso(self, task, kwargs):
@ -99,3 +114,23 @@ class VendorPassthru(base.VendorInterface):
ilo_common.setup_vmedia(task, kwargs['boot_iso_href'],
ramdisk_options=None)
manager_utils.node_power_action(task, states.REBOOT)
def _validate_is_it_a_supported_system(self, task):
"""Verify and raise an exception if it is not a supported system.
:param task: A TaskManager object.
:param kwargs: The arguments sent with vendor passthru.
:raises: IloOperationNotSupported, if the node is not a Gen10 or
Gen10 Plus system.
"""
node = task.node
ilo_object = ilo_common.get_ilo_object(node)
product_name = ilo_object.get_product_name()
operation = _("Event methods")
error_message = _(operation + (
" can not be performed as the driver does not support Event "
"methods on the given node"))
if 'Gen10' not in product_name:
raise exception.IloOperationNotSupported(operation=operation,
error=error_message)

View File

@ -1,3 +1,4 @@
# Copyright 2022 Hewlett Packard Enterprise Development LP
# Copyright 2014 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
@ -374,6 +375,22 @@ class IloCommonMethodsTestCase(BaseIloTest):
expected_info = dict(self.info, **ipmi_info)
self.assertEqual(expected_info, actual_info)
def test_update_redfish_properties(self):
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
redfish_info = {
"redfish_address": "1.2.3.4",
"redfish_username": "admin",
"redfish_password": "fake",
"redfish_verify_ca": None,
"redfish_system_id": "/redfish/v1/Systems/1"
}
task.node.driver_info = self.info
ilo_common.update_redfish_properties(task)
actual_info = task.node.driver_info
expected_info = dict(self.info, **redfish_info)
self.assertEqual(expected_info, actual_info)
def test__get_floppy_image_name(self):
image_name_expected = 'image-' + self.node.uuid
image_name_actual = ilo_common._get_floppy_image_name(self.node)

View File

@ -1,3 +1,4 @@
# Copyright 2022 Hewlett Packard Enterprise Development LP
# Copyright 2015 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
@ -30,6 +31,7 @@ from ironic.tests.unit.drivers.modules.ilo import test_common
class VendorPassthruTestCase(test_common.BaseIloTest):
boot_interface = 'ilo-virtual-media'
vendor_interface = 'ilo'
@mock.patch.object(manager_utils, 'node_power_action', spec_set=True,
autospec=True)
@ -95,3 +97,72 @@ class VendorPassthruTestCase(test_common.BaseIloTest):
task, info)
validate_image_prop_mock.assert_called_once_with(
task.context, 'foo')
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
autospec=True)
def test__validate_is_it_a_supported_system(
self, get_ilo_object_mock):
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
task.node.maintenance = True
ilo_mock_object = get_ilo_object_mock.return_value
ilo_mock_object.get_product_name.return_value = (
'ProLiant DL380 Gen10')
task.driver.vendor._validate_is_it_a_supported_system(task)
get_ilo_object_mock.assert_called_once_with(task.node)
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
autospec=True)
def test__validate_is_it_a_supported_system_exception(
self, get_ilo_object_mock):
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
task.node.maintenance = True
ilo_mock_object = get_ilo_object_mock.return_value
ilo_mock_object.get_product_name.return_value = (
'ProLiant DL380 Gen8')
self.assertRaises(
exception.IloOperationNotSupported,
task.driver.vendor._validate_is_it_a_supported_system, task)
@mock.patch.object(ilo_common, 'parse_driver_info',
spec_set=True, autospec=True)
@mock.patch.object(ilo_common, 'update_redfish_properties',
spec_set=True, autospec=True)
@mock.patch.object(ilo_vendor.VendorPassthru,
'_validate_is_it_a_supported_system',
spec_set=True, autospec=True)
def test_validate_create_subscription(self, validate_redfish_system_mock,
redfish_properties_mock,
driver_info_mock):
self.node.vendor_interface = 'ilo'
self.node.save()
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
d_info = {'ilo_address': '1.1.1.1',
'ilo_username': 'user',
'ilo_password': 'password',
'ilo_verify_ca': False}
driver_info_mock.return_value = d_info
redfish_properties = {'redfish_address': '1.1.1.1',
'redfish_username': 'user',
'redfish_password': 'password',
'redfish_system_id': '/redfish/v1/Systems/1',
'redfish_verify_ca': False}
redfish_properties_mock.return_value = redfish_properties
kwargs = {'Destination': 'https://someulr',
'Context': 'MyProtocol'}
task.driver.vendor.validate(task, 'create_subscription', **kwargs)
driver_info_mock.assert_called_once_with(task.node)
redfish_properties_mock.assert_called_once_with(task)
validate_redfish_system_mock.assert_called_once_with(
task.driver.vendor, task)
def test_validate_operation_exeption(self):
self.node.vendor_interface = 'ilo'
self.node.save()
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
self.assertRaises(
exception.IloOperationNotSupported,
task.driver.vendor.validate, task, 'eject_vmedia')

View File

@ -0,0 +1,7 @@
---
features:
- |
Provides vendor passthru methods for ``ilo`` and ``ilo5`` hardware types
to create, delete and get subscriptions for BMC events. These methods are
supported for ``HPE ProLiant Gen10`` and ``HPE ProLiant Gen10 Plus``
servers.