Add support for NMI(Non Maskable Interrupt)
This commit adds support for NMI for Gen9 and Gen10 servers. Note: These is no RIBCL interface to perform NMI using RIBCL. Change-Id: Iaf663443179417e47d022098c73a4776d41d4287 Partial-Bug: #1762311
This commit is contained in:
parent
60910b9257
commit
f3db9b7c8a
|
@ -39,6 +39,7 @@ SUPPORTED_RIS_METHODS = [
|
|||
'get_supported_boot_mode',
|
||||
'get_vm_status',
|
||||
'hold_pwr_btn',
|
||||
'inject_nmi',
|
||||
'insert_virtual_media',
|
||||
'press_pwr_btn',
|
||||
'reset_bios_to_default',
|
||||
|
@ -73,6 +74,7 @@ SUPPORTED_REDFISH_METHODS = [
|
|||
'get_current_boot_mode',
|
||||
'activate_license',
|
||||
'eject_virtual_media',
|
||||
'inject_nmi',
|
||||
'insert_virtual_media',
|
||||
'set_vm_status',
|
||||
'update_firmware',
|
||||
|
@ -641,3 +643,15 @@ class IloClient(operations.IloOperations):
|
|||
"""
|
||||
return self._call_method(
|
||||
'update_firmware', firmware_url, component_type)
|
||||
|
||||
def inject_nmi(self):
|
||||
"""Inject NMI, Non Maskable Interrupt.
|
||||
|
||||
Inject NMI (Non Maskable Interrupt) for a node immediately.
|
||||
|
||||
:raises: IloError, on an error from iLO
|
||||
:raises: IloConnectionError, if not able to reach iLO.
|
||||
:raises: IloCommandNotSupportedError, if the command is
|
||||
not supported on the server
|
||||
"""
|
||||
return self._call_method('inject_nmi')
|
||||
|
|
|
@ -360,3 +360,15 @@ class IloOperations(object):
|
|||
not supported on the server
|
||||
"""
|
||||
raise exception.IloCommandNotSupportedError(ERRMSG)
|
||||
|
||||
def inject_nmi(self):
|
||||
"""Inject NMI, Non Maskable Interrupt.
|
||||
|
||||
Inject NMI (Non Maskable Interrupt) for a node immediately.
|
||||
|
||||
:raises: IloError, on an error from iLO
|
||||
:raises: IloConnectionError, if not able to reach iLO.
|
||||
:raises: IloCommandNotSupportedError, if the command is
|
||||
not supported on the server
|
||||
"""
|
||||
raise exception.IloCommandNotSupportedError(ERRMSG)
|
||||
|
|
|
@ -1183,6 +1183,18 @@ class RIBCLOperations(operations.IloOperations):
|
|||
if location == 'Embedded':
|
||||
nic_dict[port] = mac
|
||||
|
||||
def inject_nmi(self):
|
||||
"""Inject NMI, Non Maskable Interrupt.
|
||||
|
||||
Inject NMI (Non Maskable Interrupt) for a node immediately.
|
||||
|
||||
: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)
|
||||
|
||||
|
||||
# The below block of code is there only for backward-compatibility
|
||||
# reasons (before commit 47608b6 for ris-support).
|
||||
|
|
|
@ -789,7 +789,8 @@ class RISOperations(rest.RestConnectorBase, operations.IloOperations):
|
|||
"""Perform requested power operation.
|
||||
|
||||
:param oper: Type of power button press to simulate.
|
||||
Supported values: 'ON', 'ForceOff' and 'ForceRestart'
|
||||
Supported values: 'ON', 'ForceOff', 'ForceRestart' and
|
||||
'Nmi'
|
||||
:raises: IloError, on an error from iLO.
|
||||
"""
|
||||
|
||||
|
@ -1820,3 +1821,16 @@ class RISOperations(rest.RestConnectorBase, operations.IloOperations):
|
|||
except exception.IloCommandNotSupportedError:
|
||||
nvn_status = False
|
||||
return nvn_status
|
||||
|
||||
def inject_nmi(self):
|
||||
"""Inject NMI, Non Maskable Interrupt.
|
||||
|
||||
Inject NMI (Non Maskable Interrupt) for a node immediately.
|
||||
|
||||
:raises: IloError, on an error from iLO
|
||||
"""
|
||||
cur_status = self.get_host_power_status()
|
||||
if cur_status != 'ON':
|
||||
raise exception.IloError("Server is not in powered on state.")
|
||||
|
||||
self._perform_power_op("Nmi")
|
||||
|
|
|
@ -1006,3 +1006,22 @@ class RedfishOperations(operations.IloOperations):
|
|||
else:
|
||||
msg = 'iSCSI initiator cannot be retrieved in BIOS boot mode'
|
||||
raise exception.IloCommandNotSupportedInBiosError(msg)
|
||||
|
||||
def inject_nmi(self):
|
||||
"""Inject NMI, Non Maskable Interrupt.
|
||||
|
||||
Inject NMI (Non Maskable Interrupt) for a node immediately.
|
||||
|
||||
:raises: IloError, on an error from iLO
|
||||
"""
|
||||
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
|
||||
if sushy_system.power_state != sushy.SYSTEM_POWER_STATE_ON:
|
||||
raise exception.IloError("Server is not in powered on state.")
|
||||
|
||||
try:
|
||||
sushy_system.reset_system(sushy.RESET_NMI)
|
||||
except sushy.exceptions.SushyError as e:
|
||||
msg = (self._('The Redfish controller failed to inject nmi to '
|
||||
'server. Error %(error)s') % {'error': str(e)})
|
||||
LOG.debug(msg)
|
||||
raise exception.IloError(msg)
|
||||
|
|
|
@ -1011,6 +1011,24 @@ class IloClientTestCase(testtools.TestCase):
|
|||
call_mock.assert_called_once_with('get_essential_properties')
|
||||
self.assertFalse(snmp_mock.called)
|
||||
|
||||
@mock.patch.object(client.IloClient, '_call_method')
|
||||
def test_inject_nmi(self, call_mock):
|
||||
self.client.inject_nmi()
|
||||
call_mock.assert_called_once_with('inject_nmi')
|
||||
|
||||
@mock.patch.object(ris.RISOperations, 'inject_nmi')
|
||||
def test_inject_nmi_gen9(self, inject_nmi_mock):
|
||||
self.client.model = 'Gen9'
|
||||
self.client.inject_nmi()
|
||||
inject_nmi_mock.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(ribcl.RIBCLOperations, 'get_product_name')
|
||||
def test_inject_nmi_gen8(self, product_mock):
|
||||
self.client.model = 'Gen8'
|
||||
self.assertRaisesRegexp(exception.IloCommandNotSupportedError,
|
||||
'not supported',
|
||||
self.client.inject_nmi)
|
||||
|
||||
|
||||
class IloRedfishClientTestCase(testtools.TestCase):
|
||||
|
||||
|
|
|
@ -1041,6 +1041,13 @@ class IloRibclTestCaseBeforeRisSupport(unittest.TestCase):
|
|||
self.ilo.set_vm_status('cdrom', 'boot_once', 'yes')
|
||||
self.assertTrue(request_ilo_mock.called)
|
||||
|
||||
@mock.patch.object(ribcl.RIBCLOperations, 'get_product_name')
|
||||
def test_inject_nmi(self, product_name_mock):
|
||||
product_name_mock.return_value = constants.GET_PRODUCT_NAME
|
||||
self.assertRaisesRegexp(exception.IloCommandNotSupportedError,
|
||||
'ProLiant DL380 G7',
|
||||
self.ilo.inject_nmi)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -1239,6 +1239,25 @@ class IloRisTestCase(testtools.TestCase):
|
|||
self.client.hold_pwr_btn()
|
||||
press_pwr_btn_mock.assert_called_once_with(pushType="PressAndHold")
|
||||
|
||||
@mock.patch.object(ris.RISOperations, '_perform_power_op')
|
||||
@mock.patch.object(ris.RISOperations, 'get_host_power_status')
|
||||
def test_inject_nmi(self, get_power_status_mock,
|
||||
perform_power_op_mock):
|
||||
get_power_status_mock.return_value = 'ON'
|
||||
self.client.inject_nmi()
|
||||
get_power_status_mock.assert_called_once_with()
|
||||
perform_power_op_mock.assert_called_once_with('Nmi')
|
||||
|
||||
@mock.patch.object(ris.RISOperations, '_perform_power_op')
|
||||
@mock.patch.object(ris.RISOperations, 'get_host_power_status')
|
||||
def test_inject_nmi_exc(self, get_power_status_mock,
|
||||
perform_power_op_mock):
|
||||
get_power_status_mock.return_value = 'OFF'
|
||||
self.assertRaises(exception.IloError,
|
||||
self.client.inject_nmi)
|
||||
get_power_status_mock.assert_called_once_with()
|
||||
self.assertFalse(perform_power_op_mock.called)
|
||||
|
||||
|
||||
class TestRISOperationsPrivateMethods(testtools.TestCase):
|
||||
|
||||
|
|
|
@ -1419,3 +1419,26 @@ class RedfishOperationsTestCase(testtools.TestCase):
|
|||
'iSCSI initiator cannot be retrieved in '
|
||||
'BIOS boot mode',
|
||||
self.rf_client.get_iscsi_initiator_info)
|
||||
|
||||
def test_inject_nmi(self):
|
||||
self.sushy.get_system().power_state = sushy.SYSTEM_POWER_STATE_ON
|
||||
self.rf_client.inject_nmi()
|
||||
self.sushy.get_system().reset_system.assert_called_once_with(
|
||||
sushy.RESET_NMI)
|
||||
|
||||
def test_inject_nmi_power_off(self):
|
||||
self.sushy.get_system().power_state = sushy.SYSTEM_POWER_STATE_OFF
|
||||
self.assertRaisesRegex(
|
||||
exception.IloError,
|
||||
'Server is not in powered on state.',
|
||||
self.rf_client.inject_nmi)
|
||||
self.assertFalse(self.sushy.get_system().reset_system.called)
|
||||
|
||||
def test_inject_nmi_sushy_exc(self):
|
||||
self.sushy.get_system().power_state = sushy.SYSTEM_POWER_STATE_ON
|
||||
self.sushy.get_system().reset_system.side_effect = (
|
||||
sushy.exceptions.SushyError)
|
||||
self.assertRaisesRegex(
|
||||
exception.IloError,
|
||||
'The Redfish controller failed to inject nmi',
|
||||
self.rf_client.inject_nmi)
|
||||
|
|
Loading…
Reference in New Issue