From 8acf275f52a1225ad7683ede70717ae24f9a2ea0 Mon Sep 17 00:00:00 2001 From: Nisha Agarwal Date: Tue, 2 Feb 2016 06:49:13 +0000 Subject: [PATCH] Add supported boot modes to server capabilities Added a new function ``get_supported_boot_mode`` to ris to check the value of BIOS-UEFI class supported on the server. This method was already present in ribcl. It gets used through client interface to be used in turn by ``get_server_capabilities``. The following properties are updated as part of invoking this method: boot_mode_bios boot_mode_uefi Also, removed the unused method ``_get_server_boot_modes`` from ribcl. Added a utility method in ``ilo.common`` complementing supported boot modes extraction. Co-Authored-By: Debayan Ray Related-Bug: 1526382 Change-Id: I7a60e660a6f5e574e53128f824bae0909d66d9ff --- proliantutils/ilo/client.py | 3 +- proliantutils/ilo/common.py | 34 ++++++++++++ proliantutils/ilo/constants.py | 20 +++++++ proliantutils/ilo/mappings.py | 30 ++++++++++ proliantutils/ilo/ribcl.py | 41 +++++++------- proliantutils/ilo/ris.py | 29 ++++++++++ proliantutils/tests/ilo/test_client.py | 58 +++++++++++++++++-- proliantutils/tests/ilo/test_common.py | 13 +++++ proliantutils/tests/ilo/test_ribcl.py | 77 +++++++++++++++----------- proliantutils/tests/ilo/test_ris.py | 59 ++++++++++++++++---- 10 files changed, 295 insertions(+), 69 deletions(-) create mode 100644 proliantutils/ilo/constants.py create mode 100644 proliantutils/ilo/mappings.py diff --git a/proliantutils/ilo/client.py b/proliantutils/ilo/client.py index 9f9a0de3..3f022d83 100644 --- a/proliantutils/ilo/client.py +++ b/proliantutils/ilo/client.py @@ -36,6 +36,7 @@ SUPPORTED_RIS_METHODS = [ 'get_product_name', 'get_secure_boot_mode', 'get_server_capabilities', + 'get_supported_boot_mode', 'get_vm_status', 'hold_pwr_btn', 'insert_virtual_media', @@ -49,7 +50,6 @@ SUPPORTED_RIS_METHODS = [ 'set_one_time_boot', 'set_pending_boot_mode', 'set_secure_boot_mode', - 'get_server_capabilities', 'set_iscsi_boot_info', 'unset_iscsi_boot_info', 'set_vm_status', @@ -547,6 +547,7 @@ class IloClient(operations.IloOperations): nic_capacity = ipmi.get_nic_capacity(self.info, major_minor) if nic_capacity: capabilities.update({'nic_capacity': nic_capacity}) + if capabilities: return capabilities diff --git a/proliantutils/ilo/common.py b/proliantutils/ilo/common.py index 7e1c9c89..65af9b77 100644 --- a/proliantutils/ilo/common.py +++ b/proliantutils/ilo/common.py @@ -14,12 +14,14 @@ """Common functionalities used by both RIBCL and RIS.""" +import collections import os import re import stat import time from proliantutils import exception +from proliantutils.ilo import constants from proliantutils import log @@ -27,6 +29,10 @@ LOG = log.get_logger(__name__) ILO_VER_STR_PATTERN = r"\d+\.\d+" +# Representation of supported boot modes +SupportedBootModes = collections.namedtuple( + 'SupportedBootModes', ['boot_mode_bios', 'boot_mode_uefi']) + def wait_for_operation_to_complete( has_operation_completed, retries=10, delay_bw_retries=5, @@ -218,3 +224,31 @@ def get_major_minor(ilo_ver_str): return None except Exception: return None + + +def get_supported_boot_modes(supported_boot_mode_constant): + """Retrieves the server supported boot modes + + It retrieves the server supported boot modes as a namedtuple + containing 'boot_mode_bios' as 'true'/'false' (in string format) + and 'boot_mode_uefi' again as true'/'false'. + :param supported_boot_mode_constant: supported boot_mode constant + :returns: A namedtuple containing ``boot_mode_bios`` and + ``boot_mode_uefi`` with 'true'/'false' set accordingly for + legacy BIOS and UEFI boot modes. + """ + boot_mode_bios = 'false' + boot_mode_uefi = 'false' + if (supported_boot_mode_constant == + constants.SUPPORTED_BOOT_MODE_LEGACY_BIOS_ONLY): + boot_mode_bios = 'true' + elif (supported_boot_mode_constant == + constants.SUPPORTED_BOOT_MODE_UEFI_ONLY): + boot_mode_uefi = 'true' + elif (supported_boot_mode_constant == + constants.SUPPORTED_BOOT_MODE_LEGACY_BIOS_AND_UEFI): + boot_mode_bios = 'true' + boot_mode_uefi = 'true' + + return SupportedBootModes(boot_mode_bios=boot_mode_bios, + boot_mode_uefi=boot_mode_uefi) diff --git a/proliantutils/ilo/constants.py b/proliantutils/ilo/constants.py new file mode 100644 index 00000000..d6bdc843 --- /dev/null +++ b/proliantutils/ilo/constants.py @@ -0,0 +1,20 @@ +# Copyright 2017 Hewlett Packard Enterprise Development LP +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +# SUPPORTED_BOOT_MODE constants + +SUPPORTED_BOOT_MODE_LEGACY_BIOS_ONLY = 'legacy bios only' +SUPPORTED_BOOT_MODE_UEFI_ONLY = 'uefi only' +SUPPORTED_BOOT_MODE_LEGACY_BIOS_AND_UEFI = 'legacy bios and uefi' diff --git a/proliantutils/ilo/mappings.py b/proliantutils/ilo/mappings.py new file mode 100644 index 00000000..b578dc74 --- /dev/null +++ b/proliantutils/ilo/mappings.py @@ -0,0 +1,30 @@ +# Copyright 2017 Hewlett Packard Enterprise Development LP +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from proliantutils.ilo import constants + + +# Supported boot mode mappings +GET_SUPPORTED_BOOT_MODE_RIBCL_MAP = { + 'LEGACY_ONLY': constants.SUPPORTED_BOOT_MODE_LEGACY_BIOS_ONLY, + 'UEFI_ONLY': constants.SUPPORTED_BOOT_MODE_UEFI_ONLY, + 'LEGACY_UEFI': constants.SUPPORTED_BOOT_MODE_LEGACY_BIOS_AND_UEFI, +} + +GET_SUPPORTED_BOOT_MODE_RIS_MAP = { + 0: constants.SUPPORTED_BOOT_MODE_LEGACY_BIOS_ONLY, + 3: constants.SUPPORTED_BOOT_MODE_UEFI_ONLY, + 2: constants.SUPPORTED_BOOT_MODE_LEGACY_BIOS_AND_UEFI, +} diff --git a/proliantutils/ilo/ribcl.py b/proliantutils/ilo/ribcl.py index e071bf4f..3a0b9347 100644 --- a/proliantutils/ilo/ribcl.py +++ b/proliantutils/ilo/ribcl.py @@ -31,6 +31,7 @@ import six from proliantutils import exception from proliantutils.ilo import common from proliantutils.ilo import firmware_controller +from proliantutils.ilo import mappings from proliantutils.ilo import operations from proliantutils import log @@ -472,10 +473,21 @@ class RIBCLOperations(operations.IloOperations): return data['GET_PENDING_BOOT_MODE']['BOOT_MODE']['VALUE'] def get_supported_boot_mode(self): - """Retrieves the supported boot mode.""" + """Retrieves the supported boot mode. + + :returns: any one of the following proliantutils.ilo.constants: + + SUPPORTED_BOOT_MODE_LEGACY_BIOS_ONLY, + SUPPORTED_BOOT_MODE_UEFI_ONLY, + SUPPORTED_BOOT_MODE_LEGACY_BIOS_AND_UEFI + + """ data = self._execute_command( 'GET_SUPPORTED_BOOT_MODE', 'SERVER_INFO', 'read') - return data['GET_SUPPORTED_BOOT_MODE']['SUPPORTED_BOOT_MODE']['VALUE'] + supported_boot_mode = ( + data['GET_SUPPORTED_BOOT_MODE']['SUPPORTED_BOOT_MODE']['VALUE']) + return mappings.GET_SUPPORTED_BOOT_MODE_RIBCL_MAP.get( + supported_boot_mode) def set_pending_boot_mode(self, value): """Configures the boot mode of the system from a specific boot mode.""" @@ -791,23 +803,6 @@ class RIBCLOperations(operations.IloOperations): return_value = {'properties': properties, 'macs': macs} return return_value - def _get_server_boot_modes(self): - """Gets boot modes supported by the server - - :returns: a dictionary of supported boot modes or None. - :raises:IloError, if iLO returns an error in command execution. - """ - bootmode = self.get_supported_boot_mode() - if bootmode == 'LEGACY_ONLY': - BootMode = ['LEGACY'] - elif bootmode == 'LEGACY_UEFI': - BootMode = ['LEGACY', 'UEFI'] - elif bootmode == 'UEFI_ONLY': - BootMode = ['UEFI'] - else: - BootMode = None - return {'BootMode': BootMode} - def get_server_capabilities(self): """Gets server properties which can be used for scheduling @@ -815,9 +810,6 @@ class RIBCLOperations(operations.IloOperations): versions, server model. :raises: IloError, if iLO returns an error in command execution. """ - - # Commenting out the BootMode as we dont plan to add it for Kilo. - # BootMode = self._get_server_boot_modes() capabilities = {} data = self.get_host_health_data() ilo_firmware = self._get_ilo_firmware_version(data) @@ -828,6 +820,11 @@ class RIBCLOperations(operations.IloOperations): capabilities.update(rom_firmware) capabilities.update({'server_model': self.get_product_name()}) capabilities.update(self._get_number_of_gpu_devices_connected(data)) + boot_modes = common.get_supported_boot_modes( + self.get_supported_boot_mode()) + capabilities.update({ + 'boot_mode_bios': boot_modes.boot_mode_bios, + 'boot_mode_uefi': boot_modes.boot_mode_uefi}) return capabilities def _parse_memory_embedded_health(self, data): diff --git a/proliantutils/ilo/ris.py b/proliantutils/ilo/ris.py index 9391c6d7..d0591523 100755 --- a/proliantutils/ilo/ris.py +++ b/proliantutils/ilo/ris.py @@ -19,6 +19,7 @@ import hashlib from proliantutils import exception from proliantutils.ilo import common from proliantutils.ilo import firmware_controller +from proliantutils.ilo import mappings from proliantutils.ilo import operations from proliantutils import log from proliantutils import rest @@ -57,7 +58,10 @@ LOG = log.get_logger(__name__) class RISOperations(rest.RestConnectorBase, operations.IloOperations): + """iLO class for RIS interface of iLO. + Implements the class used for REST based RIS services to talk to the iLO. + """ def __init__(self, host, login, password, bios_password=None, cacert=None): super(RISOperations, self).__init__(host, login, password, @@ -821,6 +825,25 @@ class RISOperations(rest.RestConnectorBase, operations.IloOperations): # Change the Boot Mode self._change_bios_setting(boot_properties) + def get_supported_boot_mode(self): + """Retrieves the supported boot mode. + + :returns: any one of the following proliantutils.ilo.constants: + + SUPPORTED_BOOT_MODE_LEGACY_BIOS_ONLY, + SUPPORTED_BOOT_MODE_UEFI_ONLY, + SUPPORTED_BOOT_MODE_LEGACY_BIOS_AND_UEFI + + """ + system = self._get_host_details() + bios_uefi_class_val = 0 # value for bios_only boot mode + if ('Bios' in system['Oem']['Hp'] and + 'UefiClass' in system['Oem']['Hp']['Bios']): + bios_uefi_class_val = (system['Oem']['Hp'] + ['Bios']['UefiClass']) + return mappings.GET_SUPPORTED_BOOT_MODE_RIS_MAP.get( + bios_uefi_class_val) + def reset_ilo_credential(self, password): """Resets the iLO password. @@ -979,6 +1002,12 @@ class RISOperations(rest.RestConnectorBase, operations.IloOperations): capabilities['rom_firmware_version'] = rom_firmware_version capabilities.update(self._get_ilo_firmware_version()) capabilities.update(self._get_number_of_gpu_devices_connected()) + boot_modes = common.get_supported_boot_modes( + self.get_supported_boot_mode()) + capabilities.update({ + 'boot_mode_bios': boot_modes.boot_mode_bios, + 'boot_mode_uefi': boot_modes.boot_mode_uefi}) + if self._get_tpm_capability(): capabilities['trusted_boot'] = 'true' diff --git a/proliantutils/tests/ilo/test_client.py b/proliantutils/tests/ilo/test_client.py index a13032b4..d3326acf 100644 --- a/proliantutils/tests/ilo/test_client.py +++ b/proliantutils/tests/ilo/test_client.py @@ -458,6 +458,11 @@ class IloClientTestCase(testtools.TestCase): self.client.get_pending_boot_mode() call_mock.assert_called_once_with('get_pending_boot_mode') + @mock.patch.object(client.IloClient, '_call_method') + def test_get_supported_boot_mode(self, call_mock): + self.client.get_supported_boot_mode() + call_mock.assert_called_once_with('get_supported_boot_mode') + @mock.patch.object(client.IloClient, '_call_method') def test_set_pending_boot_mode(self, call_mock): self.client.set_pending_boot_mode('UEFI') @@ -598,8 +603,26 @@ class IloClientTestCase(testtools.TestCase): @mock.patch.object(ribcl.RIBCLOperations, 'get_ilo_firmware_version_as_major_minor') @mock.patch.object(ribcl.RIBCLOperations, 'get_server_capabilities') - def test_get_server_capabilities_no_firmware(self, cap_mock, - maj_min_mock, nic_mock): + def test_get_server_capabilities_no_firmware(self, cap_mock, maj_min_mock, + nic_mock): + maj_min_mock.return_value = None + nic_mock.return_value = None + cap_mock.return_value = {'rom_firmware_version': 'x', + 'server_model': 'Gen8', + 'pci_gpu_devices': '2'} + expected_capabilities = {'rom_firmware_version': 'x', + 'server_model': 'Gen8', + 'pci_gpu_devices': '2'} + capabilities = self.client.get_server_capabilities() + self.assertEqual(expected_capabilities, capabilities) + nic_mock.assert_called_once_with(self.client.info, None) + + @mock.patch.object(ipmi, 'get_nic_capacity') + @mock.patch.object(ribcl.RIBCLOperations, + 'get_ilo_firmware_version_as_major_minor') + @mock.patch.object(ribcl.RIBCLOperations, 'get_server_capabilities') + def test_get_server_capabilities_no_boot_modes( + self, cap_mock, maj_min_mock, nic_mock): maj_min_mock.return_value = None nic_mock.return_value = None cap_mock.return_value = {'rom_firmware_version': 'x', @@ -621,6 +644,7 @@ class IloClientTestCase(testtools.TestCase): str_val = mm_mock.return_value = '2.10' self.client.model = 'Gen9' nic_mock.return_value = None + cap_mock.return_value = {'ilo_firmware_version': '2.10', 'rom_firmware_version': 'x', 'server_model': 'Gen9', @@ -640,8 +664,7 @@ class IloClientTestCase(testtools.TestCase): 'get_ilo_firmware_version_as_major_minor') @mock.patch.object(ipmi, 'get_nic_capacity') @mock.patch.object(ris.RISOperations, 'get_server_capabilities') - def test_get_server_capabilities_Gen9(self, cap_mock, nic_mock, - mm_mock): + def test_get_server_capabilities_Gen9(self, cap_mock, nic_mock, mm_mock): str_val = mm_mock.return_value = '2.10' self.client.model = 'Gen9' nic_mock.return_value = '10Gb' @@ -674,6 +697,33 @@ class IloClientTestCase(testtools.TestCase): self.assertFalse(ipmi_mock.called) self.assertTrue(cap_mock.called) + @mock.patch.object(ris.RISOperations, + 'get_ilo_firmware_version_as_major_minor') + @mock.patch.object(ribcl.RIBCLOperations, 'get_host_health_data') + @mock.patch.object(ris.RISOperations, + '_get_number_of_gpu_devices_connected') + @mock.patch.object(ipmi, 'get_nic_capacity') + @mock.patch.object(ris.RISOperations, 'get_server_capabilities') + def test_get_server_capabilities_no_boot_modes_Gen9( + self, cap_mock, nic_mock, gpu_mock, + host_mock, mm_mock): + str_val = mm_mock.return_value = '2.10' + self.client.model = 'Gen9' + nic_mock.return_value = None + gpu_mock.return_value = None + cap_mock.return_value = {'ilo_firmware_version': '2.10', + 'rom_firmware_version': 'x', + 'server_model': 'Gen9', + 'secure_boot': 'true'} + capabilities = self.client.get_server_capabilities() + cap_mock.assert_called_once_with() + nic_mock.assert_called_once_with(self.client.info, str_val) + expected_capabilities = {'ilo_firmware_version': '2.10', + 'rom_firmware_version': 'x', + 'server_model': 'Gen9', + 'secure_boot': 'true'} + self.assertEqual(expected_capabilities, capabilities) + @mock.patch.object(client.IloClient, '_call_method') def test_activate_license(self, call_mock): self.client.activate_license('fake-key') diff --git a/proliantutils/tests/ilo/test_common.py b/proliantutils/tests/ilo/test_common.py index d8a91d07..a0ec5647 100644 --- a/proliantutils/tests/ilo/test_common.py +++ b/proliantutils/tests/ilo/test_common.py @@ -22,6 +22,7 @@ import mock from proliantutils import exception from proliantutils.ilo import common +from proliantutils.ilo import constants from proliantutils.ilo import ribcl from proliantutils.ilo import ris from proliantutils.tests.ilo import ribcl_sample_outputs as ribcl_output @@ -227,3 +228,15 @@ class IloCommonModuleTestCase(unittest.TestCase): actual = None expected = common.get_major_minor(ver_str) self.assertEqual(actual, expected) + + @ddt.data((constants.SUPPORTED_BOOT_MODE_LEGACY_BIOS_ONLY, + ('true', 'false')), + (constants.SUPPORTED_BOOT_MODE_UEFI_ONLY, + ('false', 'true')), + (constants.SUPPORTED_BOOT_MODE_LEGACY_BIOS_AND_UEFI, + ('true', 'true'))) + @ddt.unpack + def test_get_supported_boot_modes(self, boot_mode_value, + expected_boot_modes): + actual_boot_modes = common.get_supported_boot_modes(boot_mode_value) + self.assertEqual(expected_boot_modes, actual_boot_modes) diff --git a/proliantutils/tests/ilo/test_ribcl.py b/proliantutils/tests/ilo/test_ribcl.py index faf62692..7d484552 100644 --- a/proliantutils/tests/ilo/test_ribcl.py +++ b/proliantutils/tests/ilo/test_ribcl.py @@ -20,6 +20,7 @@ import re import unittest import xml.etree.ElementTree as ET +import ddt import mock import requests from requests.packages import urllib3 @@ -27,6 +28,7 @@ from requests.packages.urllib3 import exceptions as urllib3_exceptions from proliantutils import exception from proliantutils.ilo import common +from proliantutils.ilo import constants as cons from proliantutils.ilo import ribcl from proliantutils.tests.ilo import ribcl_sample_outputs as constants @@ -92,6 +94,7 @@ class IloRibclTestCaseInitTestCase(unittest.TestCase): urllib3_exceptions.InsecureRequestWarning) +@ddt.ddt class IloRibclTestCase(unittest.TestCase): def setUp(self): @@ -313,6 +316,25 @@ class IloRibclTestCase(unittest.TestCase): except exception.IloCommandNotSupportedError as e: self.assertIn('ProLiant DL380 G7', str(e)) + @ddt.data(('LEGACY_ONLY', cons.SUPPORTED_BOOT_MODE_LEGACY_BIOS_ONLY), + ('UEFI_ONLY', cons.SUPPORTED_BOOT_MODE_UEFI_ONLY), + ('LEGACY_UEFI', cons.SUPPORTED_BOOT_MODE_LEGACY_BIOS_AND_UEFI)) + @ddt.unpack + @mock.patch.object( + ribcl.RIBCLOperations, '_execute_command', autospec=True) + def test_get_supported_boot_mode( + self, raw_boot_mode_value, expected_boot_mode_value, + _execute_command_mock): + # | GIVEN | + ret_val = {'GET_SUPPORTED_BOOT_MODE': + {'SUPPORTED_BOOT_MODE': + {'VALUE': raw_boot_mode_value}}} + _execute_command_mock.return_value = ret_val + # | WHEN | + actual_val = self.ilo.get_supported_boot_mode() + # | THEN | + self.assertEqual(expected_boot_mode_value, actual_val) + @mock.patch.object(common, 'wait_for_ilo_after_reset') @mock.patch.object(ribcl.RIBCLOperations, '_request_ilo') def test_reset_ilo(self, request_ilo_mock, status_mock): @@ -715,68 +737,59 @@ class IloRibclTestCase(unittest.TestCase): @mock.patch.object(ribcl.RIBCLOperations, 'get_product_name') @mock.patch.object(ribcl.RIBCLOperations, 'get_host_health_data') - def test_get_server_capabilities_gen8(self, health_data_mock, server_mock): + @mock.patch.object(ribcl.RIBCLOperations, 'get_supported_boot_mode') + def test_get_server_capabilities_gen8( + self, boot_mode_mock, health_data_mock, server_mock): data = constants.GET_EMBEDDED_HEALTH_OUTPUT json_data = json.loads(data) health_data_mock.return_value = json_data server_mock.return_value = 'ProLiant DL580 Gen8' + boot_mode_mock.return_value = ( + cons.SUPPORTED_BOOT_MODE_LEGACY_BIOS_AND_UEFI) + capabilities = self.ilo.get_server_capabilities() + self.assertIsInstance(capabilities, dict) self.assertIn('ilo_firmware_version', capabilities) self.assertIn('rom_firmware_version', capabilities) self.assertIn('server_model', capabilities) self.assertIn('pci_gpu_devices', capabilities) + self.assertIn('boot_mode_bios', capabilities) + self.assertIn('boot_mode_uefi', capabilities) + self.assertEqual('true', capabilities['boot_mode_bios']) + self.assertEqual('true', capabilities['boot_mode_uefi']) self.assertNotIn('secure_boot', capabilities) @mock.patch.object(ribcl.RIBCLOperations, 'get_product_name') @mock.patch.object(ribcl.RIBCLOperations, 'get_host_health_data') @mock.patch.object(ribcl.RIBCLOperations, '_get_ilo_firmware_version') @mock.patch.object(ribcl.RIBCLOperations, '_get_rom_firmware_version') - def test_get_server_capabilities_gen8_no_firmware(self, rom_mock, ilo_mock, - health_data_mock, - server_mock): + @mock.patch.object(ribcl.RIBCLOperations, 'get_supported_boot_mode') + def test_get_server_capabilities_gen8_no_firmware( + self, boot_mode_mock, rom_mock, ilo_mock, health_data_mock, + server_mock): data = constants.GET_EMBEDDED_HEALTH_OUTPUT json_data = json.loads(data) health_data_mock.return_value = json_data server_mock.return_value = 'ProLiant DL580 Gen8' ilo_mock.return_value = None rom_mock.return_value = None + boot_mode_mock.return_value = cons.SUPPORTED_BOOT_MODE_UEFI_ONLY + capabilities = self.ilo.get_server_capabilities() + self.assertIsInstance(capabilities, dict) self.assertNotIn('ilo_firmware_version', capabilities) self.assertNotIn('rom_firmware_version', capabilities) self.assertIn('server_model', capabilities) self.assertIn('pci_gpu_devices', capabilities) + self.assertIn('boot_mode_bios', capabilities) + self.assertIn('boot_mode_uefi', capabilities) + print(capabilities) + self.assertEqual('false', capabilities['boot_mode_bios']) + self.assertEqual('true', capabilities['boot_mode_uefi']) self.assertNotIn('secure_boot', capabilities) - @mock.patch.object(ribcl.RIBCLOperations, 'get_supported_boot_mode') - def test__get_server_boot_modes_bios(self, boot_mock): - boot_mock.return_value = 'LEGACY_ONLY' - expected_boot_mode = {'BootMode': ['LEGACY']} - boot_mode = self.ilo._get_server_boot_modes() - self.assertEqual(expected_boot_mode, boot_mode) - - @mock.patch.object(ribcl.RIBCLOperations, 'get_supported_boot_mode') - def test__get_server_boot_modes_bios_uefi(self, boot_mock): - boot_mock.return_value = 'LEGACY_UEFI' - expected_boot_mode = {'BootMode': ['LEGACY', 'UEFI']} - boot_mode = self.ilo._get_server_boot_modes() - self.assertEqual(expected_boot_mode, boot_mode) - - @mock.patch.object(ribcl.RIBCLOperations, 'get_supported_boot_mode') - def test__get_server_boot_modes_uefi(self, boot_mock): - boot_mock.return_value = 'UEFI_ONLY' - expected_boot_mode = {'BootMode': ['UEFI']} - boot_mode = self.ilo._get_server_boot_modes() - self.assertEqual(expected_boot_mode, boot_mode) - - @mock.patch.object(ribcl.RIBCLOperations, 'get_supported_boot_mode') - def test__get_server_boot_modes_None(self, boot_mock): - boot_mock.return_value = 'unknown' - expected_boot_mode = {'BootMode': None} - boot_mode = self.ilo._get_server_boot_modes() - self.assertEqual(expected_boot_mode, boot_mode) - def test__get_nic_boot_devices(self): data = json.loads(constants.GET_NIC_DATA) expected = ["Boot0003", "Boot0001", "Boot0004"] diff --git a/proliantutils/tests/ilo/test_ris.py b/proliantutils/tests/ilo/test_ris.py index 2f8a99c9..b3b28585 100755 --- a/proliantutils/tests/ilo/test_ris.py +++ b/proliantutils/tests/ilo/test_ris.py @@ -17,6 +17,7 @@ import json +import ddt import mock from requests.packages import urllib3 from requests.packages.urllib3 import exceptions as urllib3_exceptions @@ -24,6 +25,7 @@ import testtools from proliantutils import exception from proliantutils.ilo import common +from proliantutils.ilo import constants from proliantutils.ilo import ris from proliantutils.tests.ilo import ris_sample_outputs as ris_outputs @@ -56,6 +58,7 @@ class IloRisTestCaseInitTestCase(testtools.TestCase): urllib3_exceptions.InsecureRequestWarning) +@ddt.ddt class IloRisTestCase(testtools.TestCase): def setUp(self): @@ -334,6 +337,35 @@ class IloRisTestCase(testtools.TestCase): self.assertRaises(exception.IloInvalidInputError, self.client.set_pending_boot_mode, 'invalid') + @ddt.data((0, constants.SUPPORTED_BOOT_MODE_LEGACY_BIOS_ONLY), + (3, constants.SUPPORTED_BOOT_MODE_UEFI_ONLY), + (2, constants.SUPPORTED_BOOT_MODE_LEGACY_BIOS_AND_UEFI)) + @ddt.unpack + @mock.patch.object(ris.RISOperations, '_get_host_details', autospec=True) + def test_get_supported_boot_mode( + self, raw_boot_mode_value, expected_boot_mode_value, + _get_host_details_mock): + # | GIVEN | + system_val = {'Oem': {'Hp': {'Bios': + {'UefiClass': raw_boot_mode_value}}}} + _get_host_details_mock.return_value = system_val + # | WHEN | + actual_val = self.client.get_supported_boot_mode() + # | THEN | + self.assertEqual(expected_boot_mode_value, actual_val) + + @mock.patch.object(ris.RISOperations, '_get_host_details', autospec=True) + def test_get_supported_boot_mode_returns_legacy_bios_if_bios_atrrib_absent( + self, _get_host_details_mock): + # | GIVEN | + system_val = {'Oem': {'Hp': {'blahblah': 1234}}} + _get_host_details_mock.return_value = system_val + # | WHEN | + actual_val = self.client.get_supported_boot_mode() + # | THEN | + self.assertEqual(constants.SUPPORTED_BOOT_MODE_LEGACY_BIOS_ONLY, + actual_val) + @mock.patch.object(ris.RISOperations, '_rest_patch') @mock.patch.object(ris.RISOperations, '_get_collection') def test_reset_ilo_credential(self, collection_mock, patch_mock): @@ -412,17 +444,20 @@ class IloRisTestCase(testtools.TestCase): @mock.patch.object(ris.RISOperations, '_get_tpm_capability') @mock.patch.object(ris.RISOperations, '_get_number_of_gpu_devices_connected') + @mock.patch.object(ris.RISOperations, 'get_supported_boot_mode') @mock.patch.object(ris.RISOperations, 'get_secure_boot_mode') @mock.patch.object(ris.RISOperations, '_get_ilo_firmware_version') @mock.patch.object(ris.RISOperations, '_get_host_details') def test_get_server_capabilities(self, get_details_mock, ilo_firm_mock, - secure_mock, gpu_mock, tpm_mock, - cpu_vt_mock, nvdimm_n_mock, + secure_mock, boot_mode_mock, gpu_mock, + tpm_mock, cpu_vt_mock, nvdimm_n_mock, bios_sriov_mock): host_details = json.loads(ris_outputs.RESPONSE_BODY_FOR_REST_OP) get_details_mock.return_value = host_details ilo_firm_mock.return_value = {'ilo_firmware_version': 'iLO 4 v2.20'} gpu_mock.return_value = {'pci_gpu_devices': 2} + boot_mode_mock.return_value = ( + constants.SUPPORTED_BOOT_MODE_UEFI_ONLY) cpu_vt_mock.return_value = True secure_mock.return_value = False nvdimm_n_mock.return_value = True @@ -435,7 +470,9 @@ class IloRisTestCase(testtools.TestCase): 'pci_gpu_devices': 2, 'trusted_boot': 'true', 'cpu_vt': 'true', - 'nvdimm_n': 'true'} + 'nvdimm_n': 'true', + 'boot_mode_bios': 'false', + 'boot_mode_uefi': 'true'} capabilities = self.client.get_server_capabilities() self.assertEqual(expected_caps, capabilities) @@ -446,19 +483,19 @@ class IloRisTestCase(testtools.TestCase): @mock.patch.object(ris.RISOperations, '_get_tpm_capability') @mock.patch.object(ris.RISOperations, '_get_number_of_gpu_devices_connected') + @mock.patch.object(ris.RISOperations, 'get_supported_boot_mode') @mock.patch.object(ris.RISOperations, 'get_secure_boot_mode') @mock.patch.object(ris.RISOperations, '_get_ilo_firmware_version') @mock.patch.object(ris.RISOperations, '_get_host_details') - def test_get_server_capabilities_tp_absent(self, - get_details_mock, - ilo_firm_mock, secure_mock, - gpu_mock, tpm_mock, - cpu_vt_mock, nvdimm_n_mock, - bios_sriov_mock): + def test_get_server_capabilities_tp_absent( + self, get_details_mock, ilo_firm_mock, secure_mock, boot_mode_mock, + gpu_mock, tpm_mock, cpu_vt_mock, nvdimm_n_mock, bios_sriov_mock): host_details = json.loads(ris_outputs.RESPONSE_BODY_FOR_REST_OP) get_details_mock.return_value = host_details ilo_firm_mock.return_value = {'ilo_firmware_version': 'iLO 4 v2.20'} gpu_mock.return_value = {'pci_gpu_devices': 2} + boot_mode_mock.return_value = ( + constants.SUPPORTED_BOOT_MODE_LEGACY_BIOS_AND_UEFI) secure_mock.return_value = False nvdimm_n_mock.return_value = True tpm_mock.return_value = False @@ -471,7 +508,9 @@ class IloRisTestCase(testtools.TestCase): 'pci_gpu_devices': 2, 'cpu_vt': 'true', 'nvdimm_n': 'true', - 'sriov_enabled': 'true'} + 'sriov_enabled': 'true', + 'boot_mode_bios': 'true', + 'boot_mode_uefi': 'true'} capabilities = self.client.get_server_capabilities() self.assertEqual(expected_caps, capabilities)