From f7d5dedc5695ab6f787d98c403584eea93974a9a Mon Sep 17 00:00:00 2001 From: kesper Date: Fri, 14 Jul 2017 11:08:30 +0000 Subject: [PATCH] Redfish: Follow-up patch for update persistent device This commits modify 'update_persistent_device' by adding new function for getting boot string for uefi target. Change-Id: Iffbd42c1f52e9afd7339deb2f6cd2f9888a01038 --- .../redfish/resources/system/bios.py | 26 ++++- .../redfish/resources/system/system.py | 58 ++++------ .../redfish/resources/system/test_bios.py | 29 +++++ .../redfish/resources/system/test_system.py | 104 +++++++----------- 4 files changed, 113 insertions(+), 104 deletions(-) diff --git a/proliantutils/redfish/resources/system/bios.py b/proliantutils/redfish/resources/system/bios.py index 85ad4d8f..66562685 100644 --- a/proliantutils/redfish/resources/system/bios.py +++ b/proliantutils/redfish/resources/system/bios.py @@ -82,9 +82,9 @@ class BIOSPendingSettings(base.ResourceBase): :param boot_mode: either sys_cons.BIOS_BOOT_MODE_LEGACY_BIOS, sys_cons.BIOS_BOOT_MODE_UEFI. """ - bios_properties = {} - bios_properties['BootMode'] = ( - mappings.GET_BIOS_BOOT_MODE_MAP_REV.get(boot_mode)) + bios_properties = { + 'BootMode': mappings.GET_BIOS_BOOT_MODE_MAP_REV.get(boot_mode) + } if boot_mode == sys_cons.BIOS_BOOT_MODE_UEFI: bios_properties['UefiOptimizedBoot'] = 'Enabled' @@ -129,3 +129,23 @@ class BIOSBootSettings(base.ResourceBase): if val in boot_string: return key return sushy.BOOT_SOURCE_TARGET_NONE + + def get_uefi_boot_string(self, mac): + """Get uefi iscsi boot string for the host + + :returns: iscsi boot string for the system + :raises: IloError, on an error from iLO. + """ + boot_sources = self.boot_sources + if not boot_sources: + msg = ('Boot sources are not found') + LOG.debug(msg) + raise exception.IloError(msg) + + for boot_source in boot_sources: + if (mac.upper() in boot_source['UEFIDevicePath'] and + 'iSCSI' in boot_source['UEFIDevicePath']): + return boot_source['StructuredBootString'] + else: + msg = ('MAC provided "%s" is Invalid' % mac) + raise exception.IloInvalidInputError(msg) diff --git a/proliantutils/redfish/resources/system/system.py b/proliantutils/redfish/resources/system/system.py index 7c913afa..44321aab 100644 --- a/proliantutils/redfish/resources/system/system.py +++ b/proliantutils/redfish/resources/system/system.py @@ -21,17 +21,16 @@ from sushy.resources.system import system from proliantutils import exception from proliantutils import log from proliantutils.redfish.resources.system import bios -from proliantutils.redfish.resources.system import constants as sys_cons from proliantutils.redfish.resources.system import mappings from proliantutils.redfish import utils LOG = log.get_logger(__name__) PERSISTENT_BOOT_DEVICE_MAP = { - 'CDROM': sys_cons.BOOT_SOURCE_TARGET_CD, - 'NETWORK': sys_cons.BOOT_SOURCE_TARGET_PXE, - 'ISCSI': sys_cons.BOOT_SOURCE_TARGET_UEFI_TARGET, - 'HDD': sys_cons.BOOT_SOURCE_TARGET_HDD + '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 } @@ -118,40 +117,27 @@ class HPESystem(system.System): :raises: IloError, on an error from iLO. :raises: IloInvalidInputError, if the given input is not valid. """ - new_device = devices[0] - tenure = 'Continuous' if persistent else 'Once' + device = PERSISTENT_BOOT_DEVICE_MAP.get(devices[0].upper()) - try: - boot_sources = self.bios_settings.boot_settings.boot_sources - except sushy.exceptions.SushyError: - msg = ('The BIOS Boot Settings was not found.') - raise exception.IloError(msg) - - if devices[0].upper() in PERSISTENT_BOOT_DEVICE_MAP: - new_device = PERSISTENT_BOOT_DEVICE_MAP[devices[0].upper()] - - new_boot_settings = {} - if new_device is 'UefiTarget': + if device == sushy.BOOT_SOURCE_TARGET_UEFI_TARGET: if not mac: - msg = ('Mac is needed for iscsi uefi boot') + msg = ('Mac is needed for uefi iscsi boot') raise exception.IloInvalidInputError(msg) - boot_string = None - for boot_source in boot_sources: - if(mac.upper() in boot_source['UEFIDevicePath'] and - 'iSCSI' in boot_source['UEFIDevicePath']): - boot_string = boot_source['StructuredBootString'] - break + try: + uefi_boot_string = (self.bios_settings.boot_settings. + get_uefi_boot_string(mac)) + except sushy.exceptions.SushyError: + msg = ('The BIOS Boot Settings was not found.') + raise exception.IloError(msg) - if not boot_string: - msg = ('MAC provided "%s" is Invalid' % mac) - raise exception.IloInvalidInputError(msg) + uefi_boot_settings = { + 'Boot': {'UefiTargetBootSourceOverride': uefi_boot_string} + } + self._conn.patch(self.path, data=uefi_boot_settings) + elif device is None: + device = sushy.BOOT_SOURCE_TARGET_NONE - uefi_boot_settings = {} - uefi_boot_settings['Boot'] = ( - {'UefiTargetBootSourceOverride': boot_string}) - self._conn.patch(self._path, uefi_boot_settings) - - new_boot_settings['Boot'] = {'BootSourceOverrideEnabled': tenure, - 'BootSourceOverrideTarget': new_device} - self._conn.patch(self._path, new_boot_settings) + tenure = (sushy.BOOT_SOURCE_ENABLED_CONTINUOUS + if persistent else sushy.BOOT_SOURCE_ENABLED_ONCE) + self.set_system_boot_source(device, enabled=tenure) diff --git a/proliantutils/tests/redfish/resources/system/test_bios.py b/proliantutils/tests/redfish/resources/system/test_bios.py index ba8965c6..693490b5 100644 --- a/proliantutils/tests/redfish/resources/system/test_bios.py +++ b/proliantutils/tests/redfish/resources/system/test_bios.py @@ -184,3 +184,32 @@ class BIOSBootSettingsTestCase(testtools.TestCase): exception.IloError, 'Boot sources or persistent boot config order not found', self.bios_boot_inst.get_persistent_boot_device) + + def test_get_uefi_boot_string(self): + with open('proliantutils/tests/redfish/' + 'json_samples/bios_boot.json', 'r') as f: + boot_json = (json.loads(f.read())['Default']) + self.bios_boot_inst.boot_sources = boot_json['BootSources'] + result = self.bios_boot_inst.get_uefi_boot_string('C4346BB7EF30') + self.assertEqual(result, 'NIC.LOM.1.1.iSCSI') + + def test_get_uefi_boot_string_boot_sources_is_none(self): + with open('proliantutils/tests/redfish/' + 'json_samples/bios_boot.json', 'r') as f: + boot_json = ( + json.loads(f.read())['BIOS_boot_without_boot_sources']) + self.bios_boot_inst.boot_sources = boot_json['BootSources'] + self.assertRaisesRegex( + exception.IloError, + 'Boot sources are not found', + self.bios_boot_inst.get_uefi_boot_string, '123456') + + def test_get_uefi_boot_string_mac_invalid(self): + with open('proliantutils/tests/redfish/' + 'json_samples/bios_boot.json', 'r') as f: + boot_json = (json.loads(f.read())['Default']) + self.bios_boot_inst.boot_sources = boot_json['BootSources'] + self.assertRaisesRegex( + exception.IloError, + 'MAC provided "123456" is Invalid', + self.bios_boot_inst.get_uefi_boot_string, '123456') diff --git a/proliantutils/tests/redfish/resources/system/test_system.py b/proliantutils/tests/redfish/resources/system/test_system.py index 2f947950..3384d3ee 100644 --- a/proliantutils/tests/redfish/resources/system/test_system.py +++ b/proliantutils/tests/redfish/resources/system/test_system.py @@ -23,6 +23,7 @@ from proliantutils import exception from proliantutils.redfish.resources.system import bios from proliantutils.redfish.resources.system import constants as sys_cons from proliantutils.redfish.resources.system import system +from sushy.resources.system import system as sushy_system class HPESystemTestCase(testtools.TestCase): @@ -81,37 +82,29 @@ class HPESystemTestCase(testtools.TestCase): self.sys_inst.bios_settings) self.conn.get.return_value.json.assert_not_called() - def test_update_persistent_boot_persistent(self): - with open('proliantutils/tests/redfish/' - 'json_samples/bios.json', 'r') as f: - bios_mock = json.loads(f.read()) - with open('proliantutils/tests/redfish/' - 'json_samples/bios_boot.json', 'r') as g: - boot_mock = json.loads(g.read()) - self.conn.get.return_value.json.side_effect = [bios_mock['Default'], - boot_mock['Default']] - self.sys_inst.update_persistent_boot(['CDROM'], True) - data = {} - data['Boot'] = {'BootSourceOverrideEnabled': 'Continuous', - 'BootSourceOverrideTarget': 'Cd'} - self.sys_inst._conn.patch.assert_called_once_with( - '/redfish/v1/Systems/1', data) + @mock.patch.object(sushy_system.System, 'set_system_boot_source') + def test_update_persistent_boot_persistent(self, + set_system_boot_source_mock): + self.sys_inst.update_persistent_boot(['CDROM'], persistent=True) + set_system_boot_source_mock.assert_called_once_with( + sushy.BOOT_SOURCE_TARGET_CD, + enabled=sushy.BOOT_SOURCE_ENABLED_CONTINUOUS) - def test_update_persistent_boot_not_persistent(self): - with open('proliantutils/tests/redfish/' - 'json_samples/bios.json', 'r') as f: - bios_mock = json.loads(f.read()) - with open('proliantutils/tests/redfish/' - 'json_samples/bios_boot.json', 'r') as f: - boot_mock = json.loads(f.read()) - self.conn.get.return_value.json.side_effect = [bios_mock['Default'], - boot_mock['Default']] - self.sys_inst.update_persistent_boot(['CDROM'], False) - data = {} - data['Boot'] = {'BootSourceOverrideEnabled': 'Once', - 'BootSourceOverrideTarget': 'Cd'} - self.sys_inst._conn.patch.assert_called_once_with( - '/redfish/v1/Systems/1', data) + @mock.patch.object(sushy_system.System, 'set_system_boot_source') + def test_update_persistent_boot_device_unknown_persistent( + self, set_system_boot_source_mock): + self.sys_inst.update_persistent_boot(['unknown'], persistent=True) + set_system_boot_source_mock.assert_called_once_with( + sushy.BOOT_SOURCE_TARGET_NONE, + enabled=sushy.BOOT_SOURCE_ENABLED_CONTINUOUS) + + @mock.patch.object(sushy_system.System, 'set_system_boot_source') + def test_update_persistent_boot_not_persistent( + self, set_system_boot_source_mock): + self.sys_inst.update_persistent_boot(['CDROM'], persistent=False) + set_system_boot_source_mock.assert_called_once_with( + sushy.BOOT_SOURCE_TARGET_CD, + enabled=sushy.BOOT_SOURCE_ENABLED_ONCE) def test_update_persistent_boot_uefi_target(self): with open('proliantutils/tests/redfish/' @@ -119,49 +112,30 @@ class HPESystemTestCase(testtools.TestCase): bios_mock = json.loads(f.read()) with open('proliantutils/tests/redfish/' 'json_samples/bios_boot.json', 'r') as f: - boot_mock = json.loads(f.read()) - self.conn.get.return_value.json.side_effect = [bios_mock['Default'], - boot_mock['Default']] + bios_boot_mock = json.loads(f.read()) + self.conn.get.return_value.json.reset() + self.conn.get.return_value.json.side_effect = ( + [bios_mock['Default'], bios_boot_mock['Default']]) self.sys_inst.update_persistent_boot(['ISCSI'], persistent=True, mac='C4346BB7EF30') - data = {} - data['Boot'] = {'UefiTargetBootSourceOverride': 'NIC.LOM.1.1.iSCSI'} - new_data = {} - new_data['Boot'] = {'BootSourceOverrideEnabled': 'Continuous', - 'BootSourceOverrideTarget': 'UefiTarget'} - calls = [mock.call('/redfish/v1/Systems/1', data), - mock.call('/redfish/v1/Systems/1', new_data)] + uefi_boot_settings = { + 'Boot': {'UefiTargetBootSourceOverride': 'NIC.LOM.1.1.iSCSI'} + } + + calls = [mock.call('/redfish/v1/Systems/1', data=uefi_boot_settings), + mock.call('/redfish/v1/Systems/1', + data={'Boot': + {'BootSourceOverrideTarget': 'UefiTarget', + 'BootSourceOverrideEnabled': 'Continuous'}})] self.sys_inst._conn.patch.assert_has_calls(calls) def test_update_persistent_boot_uefi_target_without_mac(self): - with open('proliantutils/tests/redfish/' - 'json_samples/bios.json', 'r') as f: - bios_mock = json.loads(f.read()) - with open('proliantutils/tests/redfish/' - 'json_samples/bios_boot.json', 'r') as f: - boot_mock = json.loads(f.read()) - self.conn.get.return_value.json.side_effect = [bios_mock['Default'], - boot_mock['Default']] self.assertRaisesRegex( exception.IloInvalidInputError, - 'Mac is needed for iscsi uefi boot', + 'Mac is needed for uefi iscsi boot', self.sys_inst.update_persistent_boot, ['ISCSI'], True, None) - def test_update_persistent_boot_uefi_target_invalid_mac(self): - with open('proliantutils/tests/redfish/' - 'json_samples/bios.json', 'r') as f: - bios_mock = json.loads(f.read()) - with open('proliantutils/tests/redfish/' - 'json_samples/bios_boot.json', 'r') as f: - boot_mock = json.loads(f.read()) - self.conn.get.return_value.json.side_effect = [bios_mock['Default'], - boot_mock['Default']] - self.assertRaisesRegex( - exception.IloInvalidInputError, - 'MAC provided "12345678" is Invalid', - self.sys_inst.update_persistent_boot, ['ISCSI'], True, '12345678') - - def test_update_persistent_boot_fail(self): + def test_update_persistent_boot_uefi_target_fail(self): with open('proliantutils/tests/redfish/' 'json_samples/bios.json', 'r') as f: bios_mock = json.loads(f.read()) @@ -170,4 +144,4 @@ class HPESystemTestCase(testtools.TestCase): self.assertRaisesRegex( exception.IloError, 'The BIOS Boot Settings was not found.', - self.sys_inst.update_persistent_boot, ['CDROM'], True, None) + self.sys_inst.update_persistent_boot, ['ISCSI'], True, '12345678')