Add support for retrieving system POST state

This commit adds support for retrieving system POST state for Gen9 and
Gen10 servers.

Note: These is no RIBCL interface to retrieve system POST state.

Change-Id: Ib8d99a9fa3ece9baa17b5bb37d2f87917750350e
Partial-Bug: #1762311
This commit is contained in:
Shivanand Tendulker 2018-04-09 02:53:24 -04:00 committed by paresh-sao
parent 48741568b1
commit ffe1e61cf2
13 changed files with 153 additions and 3 deletions

View File

@ -27,6 +27,7 @@ SUPPORTED_RIS_METHODS = [
'clear_secure_boot_keys',
'eject_virtual_media',
'get_current_boot_mode',
'get_host_post_state',
'get_host_power_status',
'get_http_boot_url',
'get_ilo_firmware_version_as_major_minor',
@ -64,6 +65,7 @@ SUPPORTED_RIS_METHODS = [
SUPPORTED_REDFISH_METHODS = [
'get_product_name',
'get_host_post_state',
'get_host_power_status',
'set_host_power',
'reset_server',
@ -655,3 +657,14 @@ class IloClient(operations.IloOperations):
not supported on the server
"""
return self._call_method('inject_nmi')
def get_host_post_state(self):
"""Request the current state of system POST.
Retrieves current state of system POST.
:raises: IloError, on an error from iLO
:raises: IloCommandNotSupportedError, if the command is
not supported on the server
"""
return self._call_method('get_host_post_state')

View File

@ -368,6 +368,15 @@ class IloOperations(object):
:raises: IloError, on an error from iLO
:raises: IloConnectionError, if not able to reach iLO.
"""
raise exception.IloCommandNotSupportedError(ERRMSG)
def get_host_post_state(self):
"""Request the current state of system POST
Retrieves current state of system POST.
:raises: IloError, on an error from iLO
:raises: IloCommandNotSupportedError, if the command is
not supported on the server
"""

View File

@ -1183,6 +1183,12 @@ class RIBCLOperations(operations.IloOperations):
if location == 'Embedded':
nic_dict[port] = mac
def _raise_command_not_supported(self, method):
platform = self.get_product_name()
msg = ("`%(method)s` is not supported on %(platform)s" %
{'method': method, 'platform': platform})
raise (exception.IloCommandNotSupportedError(msg))
def inject_nmi(self):
"""Inject NMI, Non Maskable Interrupt.
@ -1191,9 +1197,17 @@ class RIBCLOperations(operations.IloOperations):
:raises: IloError, on an error from iLO
:raises: IloCommandNotSupportedError
"""
platform = self.get_product_name()
msg = ("`inject_nmi` is not supported on %s" % platform)
raise exception.IloCommandNotSupportedError(msg)
self._raise_command_not_supported("inject_nmi")
def get_host_post_state(self):
"""Request the current state of system POST.
Retrieves current state of system POST.
:raises: IloError, on an error from iLO
:raises: IloCommandNotSupportedError, RIBCL do not support it.
"""
self._raise_command_not_supported("get_host_post_state")
# The below block of code is there only for backward-compatibility

View File

@ -1834,3 +1834,19 @@ class RISOperations(rest.RestConnectorBase, operations.IloOperations):
raise exception.IloError("Server is not in powered on state.")
self._perform_power_op("Nmi")
def get_host_post_state(self):
"""Get the current state of system POST.
Retrieves current state of system POST.
:returns: POST state of the server. The valida states are:-
null, Unknown, Reset, PowerOff, InPost,
InPostDiscoveryComplete and FinishedPost.
:raises: IloError, on an error from iLO
"""
system = self._get_host_details()
if 'PostState' in system['Oem']['Hp']:
return system['Oem']['Hp']['PostState']
raise exception.IloError("Attribute 'Oem/Hp/PostState' "
"not found on system.")

View File

@ -81,6 +81,16 @@ GET_SECUREBOOT_CURRENT_BOOT_MAP = {
sys_cons.SECUREBOOT_CURRENT_BOOT_DISABLED: False
}
GET_POST_STATE_MAP = {
sys_cons.POST_STATE_NULL: 'Null',
sys_cons.POST_STATE_UNKNOWN: 'Unknown',
sys_cons.POST_STATE_RESET: 'Reset',
sys_cons.POST_STATE_POWEROFF: 'PowerOff',
sys_cons.POST_STATE_INPOST: 'InPost',
sys_cons.POST_STATE_INPOSTDISCOVERY: 'InPostDiscoveryComplete',
sys_cons.POST_STATE_FINISHEDPOST: 'FinishedPost'
}
# Assuming only one system and one manager present as part of
# collection, as we are dealing with iLO's here.
PROLIANT_MANAGER_ID = '1'
@ -1027,3 +1037,16 @@ class RedfishOperations(operations.IloOperations):
'server. Error %(error)s') % {'error': str(e)})
LOG.debug(msg)
raise exception.IloError(msg)
def get_host_post_state(self):
"""Get the current state of system POST.
Retrieves current state of system POST.
:returns: POST state of the server. The valida states are:-
null, Unknown, Reset, PowerOff, InPost,
InPostDiscoveryComplete and FinishedPost.
:raises: IloError, on an error from iLO
"""
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
return GET_POST_STATE_MAP.get(sushy_system.post_state)

View File

@ -74,3 +74,12 @@ MEMORY_TYPE_NVDIMM_N = "nvdimm_n"
MEMORY_TYPE_DRAM = "dram"
MEMORY_DEVICE_TYPE_LOGICAL = "logical"
MEMORY_DEVICE_TYPE_DDR4 = "ddr4"
# System POST state related constants
POST_STATE_NULL = "null"
POST_STATE_UNKNOWN = "unknown"
POST_STATE_RESET = "reset"
POST_STATE_POWEROFF = "poweroff"
POST_STATE_INPOST = "inpost"
POST_STATE_INPOSTDISCOVERY = "inpostdiscoverycomplete"
POST_STATE_FINISHEDPOST = "finishedpost"

View File

@ -105,3 +105,13 @@ MEMORY_DEVICE_TYPE_MAP = {
'Logical': constants.MEMORY_DEVICE_TYPE_LOGICAL,
'DDR4': constants.MEMORY_DEVICE_TYPE_DDR4
}
POST_STATE_MAP = {
'Null': constants.POST_STATE_NULL,
'Unknown': constants.POST_STATE_UNKNOWN,
'Reset': constants.POST_STATE_RESET,
'PowerOff': constants.POST_STATE_POWEROFF,
'InPost': constants.POST_STATE_INPOST,
'InPostDiscoveryComplete': constants.POST_STATE_INPOSTDISCOVERY,
'FinishedPost': constants.POST_STATE_FINISHEDPOST
}

View File

@ -75,6 +75,10 @@ class HPESystem(system.System):
['Oem', 'Hpe', 'Bios', 'UefiClass'], mappings.SUPPORTED_BOOT_MODE,
default=constants.SUPPORTED_LEGACY_BIOS_ONLY)
"""System supported boot mode."""
post_state = base.MappedField(
['Oem', 'Hpe', 'PostState'], mappings.POST_STATE_MAP,
default=constants.POST_STATE_NULL)
"""System POST state"""
_hpe_actions = HpeActionsField(['Oem', 'Hpe', 'Actions'], required=True)
"""Oem specific system extensibility actions"""

View File

@ -1029,6 +1029,23 @@ class IloClientTestCase(testtools.TestCase):
'not supported',
self.client.inject_nmi)
@mock.patch.object(client.IloClient, '_call_method')
def test_get_host_post_state(self, call_mock):
self.client.get_host_post_state()
call_mock.assert_called_once_with('get_host_post_state')
@mock.patch.object(ris.RISOperations, 'get_host_post_state')
def test_get_host_post_state_gen9(self, get_host_post_state_mock):
self.client.model = 'Gen9'
self.client.get_host_post_state()
get_host_post_state_mock.assert_called_once_with()
@mock.patch.object(ribcl.RIBCLOperations, 'get_host_post_state')
def test_get_host_post_state_gen8(self, get_host_post_state_mock):
self.client.model = 'Gen8'
self.client.get_host_post_state()
get_host_post_state_mock.assert_called_once_with()
class IloRedfishClientTestCase(testtools.TestCase):

View File

@ -1048,6 +1048,12 @@ class IloRibclTestCaseBeforeRisSupport(unittest.TestCase):
'ProLiant DL380 G7',
self.ilo.inject_nmi)
@mock.patch.object(ribcl.RIBCLOperations, 'get_product_name')
def test_get_host_post_state(self, product_name_mock):
product_name_mock.return_value = constants.GET_PRODUCT_NAME
self.assertRaisesRegexp(exception.IloCommandNotSupportedError,
'ProLiant DL380 G7',
self.ilo.get_host_post_state)
if __name__ == '__main__':
unittest.main()

View File

@ -1294,6 +1294,24 @@ class IloRisTestCase(testtools.TestCase):
get_power_status_mock.assert_called_once_with()
self.assertFalse(perform_power_op_mock.called)
@mock.patch.object(ris.RISOperations, '_get_host_details')
def test_get_host_post_state(self, get_details_mock):
host_response = ris_outputs.RESPONSE_BODY_FOR_REST_OP
expected = 'PowerOff'
get_details_mock.return_value = json.loads(host_response)
result = self.client.get_host_post_state()
self.assertEqual(expected, result)
get_details_mock.assert_called_once_with()
@mock.patch.object(ris.RISOperations, '_get_host_details')
def test_get_host_post_state_exc(self, get_details_mock):
host_response = json.loads(ris_outputs.RESPONSE_BODY_FOR_REST_OP)
get_details_mock.return_value = host_response
del host_response['Oem']['Hp']['PostState']
self.assertRaises(exception.IloError,
self.client.get_host_post_state)
get_details_mock.assert_called_once_with()
class TestRISOperationsPrivateMethods(testtools.TestCase):

View File

@ -493,3 +493,7 @@ class HPESystemTestCase(testtools.TestCase):
self.assertIsInstance(self.sys_inst.storages,
storage.StorageCollection)
self.assertFalse(self.sys_inst._storages._is_stale)
def test_get_host_post_state(self):
expected = sys_cons.POST_STATE_FINISHEDPOST
self.assertEqual(expected, self.sys_inst.post_state)

View File

@ -1447,3 +1447,10 @@ class RedfishOperationsTestCase(testtools.TestCase):
exception.IloError,
'The Redfish controller failed to inject nmi',
self.rf_client.inject_nmi)
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
def test_get_host_post_state(self, get_system_mock):
post_state = mock.PropertyMock(return_value='poweroff')
type(get_system_mock.return_value).post_state = post_state
result = self.rf_client.get_host_post_state()
self.assertEqual('PowerOff', result)