Merge "Redfish: Adds APIs to support boot from http url"
This commit is contained in:
commit
c57437dc85
|
@ -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__)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -236,7 +236,7 @@
|
|||
"UefiShellStartupUrlFromDhcp": "Disabled",
|
||||
"UncoreFreqScaling": "Auto",
|
||||
"UpiPrefetcher": "Enabled",
|
||||
"UrlBootFile": "",
|
||||
"UrlBootFile": "http://w.x.y.z/ironic.iso",
|
||||
"UrlBootFile2": "",
|
||||
"UrlBootFile3": "",
|
||||
"UrlBootFile4": "",
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue