Merge "Redfish: Adds APIs to support boot from http url"

This commit is contained in:
Zuul 2020-07-30 05:23:36 +00:00 committed by Gerrit Code Review
commit c57437dc85
5 changed files with 156 additions and 7 deletions

View File

@ -119,7 +119,9 @@ SUPPORTED_REDFISH_METHODS = [
'set_iscsi_info',
'unset_iscsi_info',
'get_iscsi_initiator_info',
'set_iscsi_initiator_info'
'set_iscsi_initiator_info',
'set_http_boot_url',
'get_http_boot_url'
]
LOG = log.get_logger(__name__)

View File

@ -55,6 +55,7 @@ DEVICE_COMMON_TO_REDFISH = {
'HDD': sushy.BOOT_SOURCE_TARGET_HDD,
'CDROM': sushy.BOOT_SOURCE_TARGET_CD,
'ISCSI': sushy.BOOT_SOURCE_TARGET_UEFI_TARGET,
'UEFIHTTP': sushy.BOOT_SOURCE_TARGET_UEFI_HTTP,
'NONE': sushy.BOOT_SOURCE_TARGET_NONE
}
@ -73,6 +74,7 @@ PERSISTENT_BOOT_MAP = {
sushy.BOOT_SOURCE_TARGET_HDD: 'HDD',
sushy.BOOT_SOURCE_TARGET_CD: 'CDROM',
sushy.BOOT_SOURCE_TARGET_UEFI_TARGET: 'NETWORK',
sushy.BOOT_SOURCE_TARGET_UEFI_HTTP: 'UEFIHTTP',
sushy.BOOT_SOURCE_TARGET_NONE: 'NONE'
}
@ -568,7 +570,7 @@ class RedfishOperations(operations.IloOperations):
for item in devices:
if item.upper() not in DEVICE_COMMON_TO_REDFISH:
msg = (self._('Invalid input "%(device)s". Valid devices: '
'NETWORK, HDD, ISCSI or CDROM.') %
'NETWORK, HDD, ISCSI, UEFIHTTP or CDROM.') %
{'device': item})
raise exception.IloInvalidInputError(msg)
@ -594,7 +596,7 @@ class RedfishOperations(operations.IloOperations):
# Check if the input is valid
if device.upper() not in DEVICE_COMMON_TO_REDFISH:
msg = (self._('Invalid input "%(device)s". Valid devices: '
'NETWORK, HDD, ISCSI or CDROM.') %
'NETWORK, HDD, ISCSI, UEFIHTTP or CDROM.') %
{'device': device})
raise exception.IloInvalidInputError(msg)
@ -1276,3 +1278,52 @@ class RedfishOperations(operations.IloOperations):
"""
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
return sushy_system.get_disk_types()
def get_http_boot_url(self):
"""Sets current BIOS settings to the provided data.
:raises: IloError, on an error from iLO.
:return: Returns the setting 'UrlBootFile' if set previously.
"""
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
url = None
try:
settings = sushy_system.bios_settings.json
attributes = settings.get('Attributes')
url = attributes.get('UrlBootFile')
except sushy.exceptions.SushyError as e:
msg = (self._('The attribute "UrlBootFile" not found.'
' Error %(error)s') %
{'error': str(e)})
LOG.debug(msg)
raise exception.IloError(msg)
return url
def set_http_boot_url(self, url, is_dhcp_enabled=True):
"""Sets HTTP boot URL to boot from it.
:param: url: HTTP URL of the image to be booted on the iLO.
:param: is_dhcp_enabled: True if no static IP is set on the node and
preferred to use DHCP service running in the network.
If False, the MAC is expected to be configured with static IP.
:raises: IloError, on an error from iLO.
"""
if not url:
raise exception.IloError("Could not set http url with"
" empty URL")
data = {
'PreBootNetwork': 'Auto',
'UrlBootFile': url,
'Dhcpv4': 'Enabled' if is_dhcp_enabled else 'Disabled'
}
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
try:
settings_required = sushy_system.bios_settings.pending_settings
settings_required.update_bios_data_by_post(data)
except sushy.exceptions.SushyError as e:
msg = (self._('Could not set HTTPS URL on the iLO.'
' Error %(error)s') %
{'error': str(e)})
LOG.debug(msg)
raise exception.IloError(msg)

View File

@ -48,7 +48,8 @@ PERSISTENT_BOOT_DEVICE_MAP = {
'CDROM': sushy.BOOT_SOURCE_TARGET_CD,
'NETWORK': sushy.BOOT_SOURCE_TARGET_PXE,
'ISCSI': sushy.BOOT_SOURCE_TARGET_UEFI_TARGET,
'HDD': sushy.BOOT_SOURCE_TARGET_HDD
'HDD': sushy.BOOT_SOURCE_TARGET_HDD,
'UEFIHTTP': sushy.BOOT_SOURCE_TARGET_UEFI_HTTP
}

View File

@ -236,7 +236,7 @@
"UefiShellStartupUrlFromDhcp": "Disabled",
"UncoreFreqScaling": "Auto",
"UpiPrefetcher": "Enabled",
"UrlBootFile": "",
"UrlBootFile": "http://w.x.y.z/ironic.iso",
"UrlBootFile2": "",
"UrlBootFile3": "",
"UrlBootFile4": "",

View File

@ -555,7 +555,7 @@ class RedfishOperationsTestCase(testtools.TestCase):
self.assertRaisesRegex(
exception.IloInvalidInputError,
('Invalid input "test". Valid devices: NETWORK, '
'HDD, ISCSI or CDROM.'),
'HDD, ISCSI, UEFIHTTP or CDROM.'),
self.rf_client.update_persistent_boot, ['test'])
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
@ -578,7 +578,7 @@ class RedfishOperationsTestCase(testtools.TestCase):
self.assertRaisesRegex(
exception.IloInvalidInputError,
('Invalid input "test". Valid devices: NETWORK, '
'HDD, ISCSI or CDROM.'),
'HDD, ISCSI, UEFIHTTP or CDROM.'),
self.rf_client.set_one_time_boot, 'test')
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
@ -1913,3 +1913,98 @@ class RedfishOperationsTestCase(testtools.TestCase):
'SSD']
self.assertEqual(
['HDD', 'SSD'], self.rf_client.get_available_disk_types())
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
def test_get_http_boot_url(self, get_system_mock):
with open('proliantutils/tests/redfish/'
'json_samples/bios.json', 'r') as f:
jsonval = json.loads(f.read()).get("Default")
type(
get_system_mock.return_value.bios_settings).json = (
mock.PropertyMock(return_value=jsonval))
settings = jsonval.get('Attributes')
expected_url_boot_file = settings.get('UrlBootFile')
actual_url_boot_file = self.rf_client.get_http_boot_url()
self.assertEqual(expected_url_boot_file, actual_url_boot_file)
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
def test_get_http_boot_url_fail(self, get_system_mock):
bios_mock = mock.PropertyMock(
side_effect=sushy.exceptions.SushyError)
type(get_system_mock.return_value).bios_settings = bios_mock
self.assertRaisesRegex(
exception.IloError,
'The attribute "UrlBootFile" not found.',
self.rf_client.get_http_boot_url)
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
def test_set_http_boot_url_dhcp_default(self, system_mock):
bios_ps_mock = mock.MagicMock(spec=bios.BIOSPendingSettings)
pending_settings_mock = mock.PropertyMock(return_value=bios_ps_mock)
type(system_mock.return_value.bios_settings).pending_settings = (
pending_settings_mock)
url = 'a.b.c'
expected_parameter = {
'PreBootNetwork': 'Auto',
'UrlBootFile': 'a.b.c',
'Dhcpv4': 'Enabled'
}
self.rf_client.set_http_boot_url(url)
bios_ps_mock.update_bios_data_by_post.assert_called_once_with(
expected_parameter)
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
def test_set_http_boot_url_dhcp_enabled(self, system_mock):
bios_ps_mock = mock.MagicMock(spec=bios.BIOSPendingSettings)
pending_settings_mock = mock.PropertyMock(return_value=bios_ps_mock)
type(system_mock.return_value.bios_settings).pending_settings = (
pending_settings_mock)
dhcp_enabled = True
url = 'a.b.c'
expected_parameter = {
'PreBootNetwork': 'Auto',
'UrlBootFile': 'a.b.c',
'Dhcpv4': 'Enabled'
}
self.rf_client.set_http_boot_url(url, dhcp_enabled)
bios_ps_mock.update_bios_data_by_post.assert_called_once_with(
expected_parameter)
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
def test_set_http_boot_url_dhcp_disabled(self, system_mock):
bios_ps_mock = mock.MagicMock(spec=bios.BIOSPendingSettings)
pending_settings_mock = mock.PropertyMock(return_value=bios_ps_mock)
type(system_mock.return_value.bios_settings).pending_settings = (
pending_settings_mock)
dhcp_enabled = False
url = 'a.b.c'
expected_parameter = {
'PreBootNetwork': 'Auto',
'UrlBootFile': 'a.b.c',
'Dhcpv4': 'Disabled'
}
self.rf_client.set_http_boot_url(url, dhcp_enabled)
bios_ps_mock.update_bios_data_by_post.assert_called_once_with(
expected_parameter)
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
def test_set_http_boot_url_raises_exception(self, system_mock):
pending_settings_mock = mock.PropertyMock(
side_effect=sushy.exceptions.SushyError)
type(system_mock.return_value.bios_settings).pending_settings = (
pending_settings_mock)
dhcp_enabled = True
url = 'a.b.c'
self.assertRaisesRegex(
exception.IloError,
'Could not set HTTPS URL on the iLO.',
self.rf_client.set_http_boot_url, url, dhcp_enabled)