Merge "Add RIS support for power operations"

This commit is contained in:
Jenkins 2016-06-08 04:28:54 +00:00 committed by Gerrit Code Review
commit dab917ddc6
4 changed files with 220 additions and 0 deletions

View File

@ -32,10 +32,14 @@ SUPPORTED_RIS_METHODS = [
'get_product_name',
'get_secure_boot_mode',
'get_vm_status',
'hold_pwr_btn',
'insert_virtual_media',
'press_pwr_btn',
'reset_bios_to_default',
'reset_ilo_credential',
'reset_secure_boot_keys',
'reset_server',
'set_host_power',
'set_http_boot_url',
'set_one_time_boot',
'set_pending_boot_mode',

View File

@ -43,6 +43,11 @@ DEVICE_COMMON_TO_RIS = {'NETWORK': 'Pxe',
DEVICE_RIS_TO_COMMON = dict(
(v, k) for (k, v) in DEVICE_COMMON_TO_RIS.items())
POWER_STATE = {
'ON': 'On',
'OFF': 'ForceOff',
}
LOG = log.get_logger(__name__)
@ -710,6 +715,88 @@ class RISOperations(operations.IloOperations):
data = self._get_host_details()
return data['Power'].upper()
def _perform_power_op(self, oper):
"""Perform requested power operation.
:param oper: Type of power button press to simulate.
Supported values: 'ON', 'ForceOff' and 'ForceRestart'
:raises: IloError, on an error from iLO.
"""
power_settings = {"Action": "Reset",
"ResetType": oper}
systems_uri = "/rest/v1/Systems/1"
status, headers, response = self._rest_post(systems_uri, None,
power_settings)
if status >= 300:
msg = self._get_extended_error(response)
raise exception.IloError(msg)
def reset_server(self):
"""Resets the server.
:raises: IloError, on an error from iLO.
"""
self._perform_power_op("ForceRestart")
def _press_pwr_btn(self, pushType="Press"):
"""Simulates a physical press of the server power button.
:param pushType: Type of power button press to simulate
Supported values are: 'Press' and 'PressAndHold'
:raises: IloError, on an error from iLO.
"""
power_settings = {"Action": "PowerButton",
"Target": "/Oem/Hp",
"PushType": pushType}
systems_uri = "/rest/v1/Systems/1"
status, headers, response = self._rest_post(systems_uri, None,
power_settings)
if status >= 300:
msg = self._get_extended_error(response)
raise exception.IloError(msg)
def press_pwr_btn(self):
"""Simulates a physical press of the server power button.
:raises: IloError, on an error from iLO.
"""
self._press_pwr_btn()
def hold_pwr_btn(self):
"""Simulate a physical press and hold of the server power button.
:raises: IloError, on an error from iLO.
"""
self._press_pwr_btn(pushType="PressAndHold")
def set_host_power(self, power):
"""Toggle the power button of server.
:param power: 'ON' or 'OFF'
:raises: IloError, on an error from iLO.
"""
power = power.upper()
if (power is not None) and (power not in POWER_STATE):
msg = ("Invalid input '%(pow)s'. "
"The expected input is ON or OFF." %
{'pow': power})
raise exception.IloInvalidInputError(msg)
# Check current power status, do not act if it's in requested state.
cur_status = self.get_host_power_status()
if cur_status == power:
LOG.debug(self._("Node is already in '%(power)s' power state."),
{'power': power})
return
self._perform_power_op(POWER_STATE[power])
def get_http_boot_url(self):
"""Request the http boot url from system in uefi boot mode.

View File

@ -513,3 +513,51 @@ class IloClientTestCase(testtools.TestCase):
_call_method_mock.assert_called_once_with('update_firmware',
some_url,
some_component_type)
@mock.patch.object(ris.RISOperations, 'hold_pwr_btn')
def test_hold_pwr_btn_gen9(self, hold_pwr_btn_mock):
self.client.model = 'Gen9'
self.client.hold_pwr_btn()
self.assertTrue(hold_pwr_btn_mock.called)
@mock.patch.object(ribcl.RIBCLOperations, 'hold_pwr_btn')
def test_hold_pwr_btn_gen8(self, hold_pwr_btn_mock):
self.client.model = 'Gen8'
self.client.hold_pwr_btn()
self.assertTrue(hold_pwr_btn_mock.called)
@mock.patch.object(ris.RISOperations, 'set_host_power')
def test_set_host_power_gen9(self, set_host_power_mock):
self.client.model = 'Gen9'
self.client.set_host_power('ON')
set_host_power_mock.assert_called_once_with('ON')
@mock.patch.object(ribcl.RIBCLOperations, 'set_host_power')
def test_set_host_power_gen8(self, set_host_power_mock):
self.client.model = 'Gen8'
self.client.set_host_power('ON')
set_host_power_mock.assert_called_once_with('ON')
@mock.patch.object(ris.RISOperations, 'press_pwr_btn')
def test_press_pwr_btn_gen9(self, press_pwr_btn_mock):
self.client.model = 'Gen9'
self.client.press_pwr_btn()
self.assertTrue(press_pwr_btn_mock.called)
@mock.patch.object(ribcl.RIBCLOperations, 'press_pwr_btn')
def test_press_pwr_btn_gen8(self, press_pwr_btn_mock):
self.client.model = 'Gen8'
self.client.press_pwr_btn()
self.assertTrue(press_pwr_btn_mock.called)
@mock.patch.object(ris.RISOperations, 'reset_server')
def test_reset_server_gen9(self, reset_server_mock):
self.client.model = 'Gen9'
self.client.reset_server()
self.assertTrue(reset_server_mock.called)
@mock.patch.object(ribcl.RIBCLOperations, 'reset_server')
def test_reset_server_gen8(self, reset_server_mock):
self.client.model = 'Gen8'
self.client.reset_server()
self.assertTrue(reset_server_mock.called)

View File

@ -948,6 +948,41 @@ class IloRisTestCase(testtools.TestCase):
self.assertRaises(exception.IloError,
self.client.get_firmware_update_progress)
@mock.patch.object(ris.RISOperations, 'get_host_power_status')
def test_set_host_power_no_change(self, host_power_status_mock):
host_power_status_mock.return_value = 'ON'
self.client.set_host_power('on')
self.assertTrue(host_power_status_mock.called)
@mock.patch.object(ris.RISOperations, 'get_host_power_status')
def test_set_host_power_exc(self, host_power_status_mock):
self.assertRaises(exception.IloInvalidInputError,
self.client.set_host_power, 'invalid')
@mock.patch.object(ris.RISOperations, '_perform_power_op')
@mock.patch.object(ris.RISOperations, 'get_host_power_status')
def test_set_host_power_change(self, host_power_status_mock,
perform_power_op_mock):
host_power_status_mock.return_value = 'ON'
self.client.set_host_power('off')
host_power_status_mock.assert_called_once_with()
perform_power_op_mock.assert_called_once_with('ForceOff')
@mock.patch.object(ris.RISOperations, '_perform_power_op')
def test_reset_server(self, mock_perform_power):
self.client.reset_server()
mock_perform_power.assert_called_once_with("ForceRestart")
@mock.patch.object(ris.RISOperations, '_press_pwr_btn')
def test_hold_pwr_btn(self, press_pwr_btn_mock):
self.client.hold_pwr_btn()
press_pwr_btn_mock.assert_called_once_with(pushType="PressAndHold")
@mock.patch.object(ris.RISOperations, '_press_pwr_btn')
def test_press_pwr_btn(self, press_pwr_btn_mock):
self.client.hold_pwr_btn()
press_pwr_btn_mock.assert_called_once_with(pushType="PressAndHold")
class TestRISOperationsPrivateMethods(testtools.TestCase):
@ -1673,3 +1708,49 @@ class TestRISOperationsPrivateMethods(testtools.TestCase):
# | WHEN | & | THEN |
self.assertRaises(exception.IloCommandNotSupportedError,
self.client._get_firmware_update_service_resource)
@mock.patch.object(ris.RISOperations, '_rest_post')
def test_press_pwr_btn(self, rest_post_mock):
systems_uri = "/rest/v1/Systems/1"
new_pow_settings = {"Action": "PowerButton",
"Target": "/Oem/Hp",
"PushType": "Press"}
rest_post_mock.return_value = (200, ris_outputs.GET_HEADERS,
ris_outputs.REST_POST_RESPONSE)
self.client._press_pwr_btn()
rest_post_mock.assert_called_once_with(systems_uri, None,
new_pow_settings)
@mock.patch.object(ris.RISOperations, '_rest_post')
def test_press_pwr_btn_patch_fail(self, rest_post_mock):
systems_uri = "/rest/v1/Systems/1"
new_pow_settings = {"Action": "PowerButton",
"Target": "/Oem/Hp",
"PushType": "Press"}
rest_post_mock.return_value = (301, ris_outputs.GET_HEADERS,
ris_outputs.REST_FAILURE_OUTPUT)
self.assertRaises(exception.IloError,
self.client._press_pwr_btn, 'Press')
rest_post_mock.assert_called_once_with(systems_uri, None,
new_pow_settings)
@mock.patch.object(ris.RISOperations, '_rest_post')
def test_perform_power_op(self, rest_post_mock):
systems_uri = "/rest/v1/Systems/1"
new_pow_settings = {"Action": "Reset", "ResetType": "ForceRestart"}
rest_post_mock.return_value = (200, ris_outputs.GET_HEADERS,
ris_outputs.REST_POST_RESPONSE)
self.client.reset_server()
rest_post_mock.assert_called_once_with(systems_uri, None,
new_pow_settings)
@mock.patch.object(ris.RISOperations, '_rest_post')
def test_perform_power_op_fail(self, rest_post_mock):
systems_uri = "/rest/v1/Systems/1"
new_pow_settings = {"Action": "Reset", "ResetType": "ForceRestart"}
rest_post_mock.return_value = (301, ris_outputs.GET_HEADERS,
ris_outputs.REST_FAILURE_OUTPUT)
self.assertRaises(exception.IloError,
self.client.reset_server)
rest_post_mock.assert_called_once_with(systems_uri, None,
new_pow_settings)