Redfish: Adds 'update_firmware' API support through redfish
This commit provides functionality to support firmware update on redish systems. Change-Id: I564f4cc69a8bb8b567e930082c1b68bb2046d747
This commit is contained in:
parent
ead74eadad
commit
e17153856b
|
@ -71,6 +71,7 @@ SUPPORTED_REDFISH_METHODS = [
|
|||
'eject_virtual_media',
|
||||
'insert_virtual_media',
|
||||
'set_vm_status'
|
||||
'update_firmware',
|
||||
]
|
||||
|
||||
LOG = log.get_logger(__name__)
|
||||
|
|
|
@ -18,6 +18,7 @@ import sushy
|
|||
|
||||
from proliantutils.redfish.resources.manager import manager
|
||||
from proliantutils.redfish.resources.system import system
|
||||
from proliantutils.redfish.resources import update_service
|
||||
from proliantutils.redfish import utils
|
||||
|
||||
|
||||
|
@ -51,3 +52,14 @@ class HPESushy(sushy.Sushy):
|
|||
"""
|
||||
return manager.HPEManager(self._conn, identity,
|
||||
redfish_version=self.redfish_version)
|
||||
|
||||
def get_update_service(self):
|
||||
"""Return a HPEUpdateService object
|
||||
|
||||
:returns: The UpdateService object
|
||||
"""
|
||||
update_service_url = utils.get_subresource_path_by(self,
|
||||
'UpdateService')
|
||||
return (update_service.
|
||||
HPEUpdateService(self._conn, update_service_url,
|
||||
redfish_version=self.redfish_version))
|
||||
|
|
|
@ -19,6 +19,7 @@ import sushy
|
|||
from sushy import utils
|
||||
|
||||
from proliantutils import exception
|
||||
from proliantutils.ilo import firmware_controller
|
||||
from proliantutils.ilo import operations
|
||||
from proliantutils import log
|
||||
from proliantutils.redfish import main
|
||||
|
@ -424,3 +425,23 @@ class RedfishOperations(operations.IloOperations):
|
|||
{'device': device, 'error': str(e)})
|
||||
LOG.debug(msg)
|
||||
raise exception.IloError(msg)
|
||||
|
||||
@firmware_controller.check_firmware_update_component
|
||||
def update_firmware(self, file_url, component_type):
|
||||
"""Updates the given firmware on the server for the given component.
|
||||
|
||||
:param file_url: location of the raw firmware file. Extraction of the
|
||||
firmware file (if in compact format) is expected to
|
||||
happen prior to this invocation.
|
||||
:param component_type: Type of component to be applied to.
|
||||
:raises: IloError, on an error from iLO.
|
||||
"""
|
||||
try:
|
||||
update_service_inst = self._sushy.get_update_service()
|
||||
update_service_inst.flash_firmware(self, file_url)
|
||||
except sushy.exceptions.SushyError as e:
|
||||
msg = (self._('The Redfish controller failed to update firmware '
|
||||
'with firmware %(file)s Error %(error)s') %
|
||||
{'file': file_url, 'error': str(e)})
|
||||
LOG.debug(msg)
|
||||
raise exception.IloError(msg)
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
# Copyright 2017 Hewlett Packard Enterprise Development LP
|
||||
#
|
||||
# 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.
|
||||
|
||||
__author__ = 'HPE'
|
||||
|
||||
import sushy
|
||||
|
||||
from sushy.resources import base
|
||||
from sushy.resources import common as sushy_common
|
||||
|
||||
from proliantutils import exception
|
||||
from proliantutils.ilo import common
|
||||
from proliantutils import log
|
||||
|
||||
|
||||
LOG = log.get_logger(__name__)
|
||||
|
||||
|
||||
class ActionsField(base.CompositeField):
|
||||
update_firmware = (sushy_common.
|
||||
ResetActionField('#UpdateService.SimpleUpdate'))
|
||||
|
||||
|
||||
class HPEUpdateService(base.ResourceBase):
|
||||
"""Class that extends the functionality of Base resource class
|
||||
|
||||
This class extends the functionality of Base resource class
|
||||
from sushy
|
||||
"""
|
||||
firmware_state = base.Field(['Oem', 'Hpe', 'State'])
|
||||
firmware_percentage = base.Field(['Oem', 'Hpe', 'FlashProgressPercent'])
|
||||
_actions = ActionsField(['Actions'], required=True)
|
||||
|
||||
def _get_firmware_update_element(self):
|
||||
"""Get the url for firmware update
|
||||
|
||||
:returns: firmware update url
|
||||
:raises: Missing resource error on missing url
|
||||
"""
|
||||
fw_update_action = self._actions.update_firmware
|
||||
if not fw_update_action:
|
||||
raise (sushy.exceptions.
|
||||
MissingActionError(action='#UpdateService.SimpleUpdate',
|
||||
resource=self._path))
|
||||
return fw_update_action
|
||||
|
||||
def flash_firmware(self, redfish_inst, file_url):
|
||||
"""Perform firmware flashing on a redfish system
|
||||
|
||||
:param file_url: url to firmware bits.
|
||||
:param redfish_inst: redfish instance
|
||||
:raises: IloError, on an error from iLO.
|
||||
"""
|
||||
action_data = {
|
||||
'ImageURI': file_url,
|
||||
}
|
||||
target_uri = self._get_firmware_update_element().target_uri
|
||||
try:
|
||||
self._conn.post(target_uri, data=action_data)
|
||||
except sushy.exceptions.SushyError as e:
|
||||
msg = (('The Redfish controller failed to update firmware '
|
||||
'with file %(file)s Error %(error)s') %
|
||||
{'file': file_url, 'error': str(e)})
|
||||
LOG.debug(msg) # noqa
|
||||
raise exception.IloError(msg)
|
||||
|
||||
self.wait_for_redfish_firmware_update_to_complete(redfish_inst)
|
||||
try:
|
||||
state, percent = self.get_firmware_update_progress()
|
||||
except sushy.exceptions.SushyError as e:
|
||||
msg = ('Failed to get firmware progress update '
|
||||
'Error %(error)s' % {'error': str(e)})
|
||||
LOG.debug(msg)
|
||||
raise exception.IloError(msg)
|
||||
|
||||
if state == "Error":
|
||||
msg = 'Unable to update firmware'
|
||||
LOG.debug(msg) # noqa
|
||||
raise exception.IloError(msg)
|
||||
elif state == "Unknown":
|
||||
msg = 'Status of firmware update not known'
|
||||
LOG.debug(msg) # noqa
|
||||
else: # "Complete" | "Idle"
|
||||
LOG.info('Flashing firmware file: %s ... done', file_url)
|
||||
|
||||
def wait_for_redfish_firmware_update_to_complete(self, redfish_object):
|
||||
"""Continuously polls for iLO firmware update to complete.
|
||||
|
||||
:param redfish_object: redfish instance
|
||||
"""
|
||||
p_state = ['Idle']
|
||||
c_state = ['Idle']
|
||||
|
||||
def has_firmware_flash_completed():
|
||||
"""Checks for completion status of firmware update operation
|
||||
|
||||
The below table shows the conditions for which the firmware update
|
||||
will be considered as DONE (be it success or error)::
|
||||
|
||||
+-----------------------------------+-----------------------------+
|
||||
| Previous state | Current state |
|
||||
+===================================+=============================+
|
||||
| Idle | Error, Complete |
|
||||
+-----------------------------------+-----------------------------+
|
||||
| Updating, Verifying, | Complete, Error, |
|
||||
| Uploading, Writing | Unknown, Idle |
|
||||
+-----------------------------------+-----------------------------+
|
||||
|
||||
:returns: True upon firmware update completion otherwise False
|
||||
"""
|
||||
curr_state, curr_percent = self.get_firmware_update_progress()
|
||||
p_state[0] = c_state[0]
|
||||
c_state[0] = curr_state
|
||||
if (((p_state[0] in ['Updating', 'Verifying',
|
||||
'Uploading', 'Writing'])
|
||||
and (c_state[0] in ['Complete', 'Error',
|
||||
'Unknown', 'Idle']))
|
||||
or (p_state[0] == 'Idle' and (c_state[0] in
|
||||
['Complete', 'Error']))):
|
||||
return True
|
||||
return False
|
||||
|
||||
common.wait_for_operation_to_complete(
|
||||
has_firmware_flash_completed,
|
||||
delay_bw_retries=30,
|
||||
failover_msg='iLO firmware update has failed.'
|
||||
)
|
||||
common.wait_for_ilo_after_reset(redfish_object)
|
||||
|
||||
def get_firmware_update_progress(self):
|
||||
"""Get the progress of the firmware update.
|
||||
|
||||
:returns: firmware update state, one of the following values:
|
||||
"Idle","Uploading","Verifying","Writing",
|
||||
"Updating","Complete","Error".
|
||||
If the update resource is not found, then "Unknown".
|
||||
:returns: firmware update progress percent
|
||||
"""
|
||||
# perform refresh
|
||||
try:
|
||||
self.refresh()
|
||||
except sushy.exceptions.SushyError as e:
|
||||
msg = (('Progress of firmware update not known. '
|
||||
'Error %(error)s') %
|
||||
{'error': str(e)})
|
||||
LOG.debug(msg)
|
||||
return "Unknown", "Unknown"
|
||||
|
||||
# NOTE: Percentage is returned None after firmware flash is completed.
|
||||
return (self.firmware_state, self.firmware_percentage)
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"@odata.context": "/redfish/v1/$metadata#UpdateService",
|
||||
"@odata.etag": "W/\"505EF3C5\"",
|
||||
"@odata.id": "/redfish/v1/UpdateService/",
|
||||
"@odata.type": "#UpdateService.v1_1_0.UpdateService",
|
||||
"Actions": {
|
||||
"#UpdateService.SimpleUpdate": {
|
||||
"target": "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate/"
|
||||
}
|
||||
},
|
||||
"Description": "iLO Update Service",
|
||||
"FirmwareInventory": {
|
||||
"@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/"
|
||||
},
|
||||
"HttpPushUri": "/cgi-bin/uploadFile",
|
||||
"Id": "UpdateService",
|
||||
"Name": "Update Service",
|
||||
"Oem": {
|
||||
"Hpe": {
|
||||
"@odata.type": "#HpeiLOUpdateServiceExt.v2_0_0.HpeiLOUpdateServiceExt",
|
||||
"Actions": {
|
||||
"#HpeiLOUpdateServiceExt.AddFromUri": {
|
||||
"target": "/redfish/v1/UpdateService/Actions/Oem/Hpe/HpeiLOUpdateServiceExt.AddFromUri/"
|
||||
},
|
||||
"#HpeiLOUpdateServiceExt.StartFirmwareIntegrityCheck": {
|
||||
"target": "/redfish/v1/UpdateService/Actions/Oem/Hpe/HpeiLOUpdateServiceExt.StartFirmwareIntegrityCheck/"
|
||||
}
|
||||
},
|
||||
"ComponentRepository": {
|
||||
"@odata.id": "/redfish/v1/UpdateService/ComponentRepository/"
|
||||
},
|
||||
"CurrentTime": "2017-06-17T09:15:05Z",
|
||||
"FlashProgressPercent": 24,
|
||||
"InstallSets": {
|
||||
"@odata.id": "/redfish/v1/UpdateService/InstallSets/"
|
||||
},
|
||||
"State": "Updating",
|
||||
"UpdateTaskQueue": {
|
||||
"@odata.id": "/redfish/v1/UpdateService/UpdateTaskQueue/"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ServiceEnabled": true,
|
||||
"SoftwareInventory": {
|
||||
"@odata.id": "/redfish/v1/UpdateService/SoftwareInventory/"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
# 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.
|
||||
|
||||
import json
|
||||
import mock
|
||||
import sushy
|
||||
import testtools
|
||||
import time
|
||||
|
||||
from proliantutils import exception
|
||||
from proliantutils.ilo import common
|
||||
from proliantutils.redfish import main
|
||||
from proliantutils.redfish import redfish
|
||||
from proliantutils.redfish.resources import update_service
|
||||
|
||||
|
||||
class HPEUpdateServiceTestCase(testtools.TestCase):
|
||||
|
||||
@mock.patch.object(main, 'HPESushy', autospec=True)
|
||||
def setUp(self, sushy_mock):
|
||||
super(HPEUpdateServiceTestCase, self).setUp()
|
||||
self.conn = mock.MagicMock()
|
||||
self.sushy = mock.MagicMock()
|
||||
sushy_mock.return_value = self.sushy
|
||||
with open('proliantutils/tests/redfish/'
|
||||
'json_samples/update_service.json', 'r') as f:
|
||||
self.conn.get.return_value.json.return_value = json.loads(f.read())
|
||||
|
||||
self.rf_client = redfish.RedfishOperations(
|
||||
'1.2.3.4', username='foo', password='bar')
|
||||
sushy_mock.assert_called_once_with(
|
||||
'https://1.2.3.4', 'foo', 'bar', '/redfish/v1/', False)
|
||||
self.us_inst = update_service.HPEUpdateService(
|
||||
self.conn, '/redfish/v1/UpdateService/1',
|
||||
redfish_version='1.0.2')
|
||||
|
||||
def test__get_firmware_update_element(self):
|
||||
value = self.us_inst._get_firmware_update_element()
|
||||
expected_uri = ('/redfish/v1/UpdateService/Actions/'
|
||||
'UpdateService.SimpleUpdate/')
|
||||
self.assertEqual(expected_uri, value.target_uri)
|
||||
|
||||
def test__get_firmware_update_element_missing_url_action(self):
|
||||
self.us_inst._actions.update_firmware = None
|
||||
self.assertRaisesRegex(
|
||||
sushy.exceptions.MissingActionError,
|
||||
'action #UpdateService.SimpleUpdate',
|
||||
self.us_inst._get_firmware_update_element)
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(update_service.HPEUpdateService,
|
||||
'get_firmware_update_progress', autospec=True)
|
||||
@mock.patch.object(update_service.HPEUpdateService,
|
||||
'wait_for_redfish_firmware_update_to_complete',
|
||||
autospec=True)
|
||||
@mock.patch.object(common, 'wait_for_ilo_after_reset', lambda x: None)
|
||||
def test_flash_firmware(self,
|
||||
wait_for_redfish_firmware_update_to_complete_mock,
|
||||
get_firmware_update_progress_mock,
|
||||
sleep_mock):
|
||||
# | GIVEN |
|
||||
target_uri = ('/redfish/v1/UpdateService/Actions/'
|
||||
'UpdateService.SimpleUpdate/')
|
||||
get_firmware_update_progress_mock.return_value = 'Complete', None
|
||||
# | WHEN |
|
||||
self.us_inst.flash_firmware(self.rf_client, 'web_url')
|
||||
# | THEN |
|
||||
self.us_inst._conn.post.assert_called_once_with(
|
||||
target_uri, data={'ImageURI': 'web_url'})
|
||||
self.assertTrue(wait_for_redfish_firmware_update_to_complete_mock.
|
||||
called)
|
||||
self.assertTrue(get_firmware_update_progress_mock.called)
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(update_service.HPEUpdateService,
|
||||
'get_firmware_update_progress', autospec=True)
|
||||
@mock.patch.object(common, 'wait_for_ilo_after_reset', lambda x: None)
|
||||
def test_flash_firmware_post_fails(self, get_firmware_update_progress_mock,
|
||||
sleep_mock):
|
||||
get_firmware_update_progress_mock.return_value = 'Complete', None
|
||||
self.us_inst._conn.post.side_effect = (
|
||||
sushy.exceptions.SushyError)
|
||||
self.assertRaisesRegex(
|
||||
exception.IloError,
|
||||
'The Redfish controller failed to update firmware',
|
||||
self.us_inst.flash_firmware, self.rf_client, 'web_url')
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(update_service.HPEUpdateService,
|
||||
'get_firmware_update_progress', autospec=True)
|
||||
@mock.patch.object(update_service.HPEUpdateService,
|
||||
'wait_for_redfish_firmware_update_to_complete',
|
||||
autospec=True)
|
||||
@mock.patch.object(common, 'wait_for_ilo_after_reset', lambda x: None)
|
||||
def test_flash_firmware_get_firmware_update_progress_throws_exception(
|
||||
self, wait_for_redfish_firmware_update_to_complete_mock,
|
||||
get_firmware_update_progress_mock, sleep_mock):
|
||||
# | GIVEN |
|
||||
self.us_inst._conn.post.return_value.status_code = 200
|
||||
get_firmware_update_progress_mock.side_effect = (
|
||||
sushy.exceptions.SushyError)
|
||||
# | WHEN & THEN|
|
||||
self.assertRaisesRegex(
|
||||
exception.IloError,
|
||||
'Failed to get firmware progress update',
|
||||
self.us_inst.flash_firmware, self.rf_client, 'web_url')
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(update_service.HPEUpdateService,
|
||||
'get_firmware_update_progress', autospec=True)
|
||||
@mock.patch.object(update_service.HPEUpdateService,
|
||||
'wait_for_redfish_firmware_update_to_complete',
|
||||
autospec=True)
|
||||
@mock.patch.object(common, 'wait_for_ilo_after_reset', lambda x: None)
|
||||
def test_flash_firmware_get_firmware_update_progress_in_error_state(
|
||||
self, wait_for_redfish_firmware_update_to_complete_mock,
|
||||
get_firmware_update_progress_mock, sleep_mock):
|
||||
# | GIVEN |
|
||||
self.us_inst._conn.post.return_value.status_code = 200
|
||||
get_firmware_update_progress_mock.side_effect = [('Error', None)]
|
||||
# | WHEN & THEN|
|
||||
self.assertRaisesRegex(
|
||||
exception.IloError,
|
||||
'Unable to update firmware',
|
||||
self.us_inst.flash_firmware, self.rf_client, 'web_url')
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(update_service.HPEUpdateService,
|
||||
'get_firmware_update_progress', autospec=True)
|
||||
@mock.patch.object(update_service.HPEUpdateService,
|
||||
'wait_for_redfish_firmware_update_to_complete',
|
||||
autospec=True)
|
||||
@mock.patch.object(common, 'wait_for_ilo_after_reset', lambda x: None)
|
||||
def test_flash_firmware_get_firmware_update_progress_in_unknown_state(
|
||||
self, wait_for_redfish_firmware_update_to_complete_mock,
|
||||
get_firmware_update_progress_mock, sleep_mock):
|
||||
# | GIVEN |
|
||||
target_uri = ('/redfish/v1/UpdateService/Actions/'
|
||||
'UpdateService.SimpleUpdate/')
|
||||
get_firmware_update_progress_mock.return_value = 'Unknown', None
|
||||
# | WHEN |
|
||||
self.us_inst.flash_firmware(self.rf_client, 'web_url')
|
||||
# | THEN |
|
||||
self.us_inst._conn.post.assert_called_once_with(
|
||||
target_uri, data={'ImageURI': 'web_url'})
|
||||
self.assertTrue(wait_for_redfish_firmware_update_to_complete_mock.
|
||||
called)
|
||||
self.assertTrue(get_firmware_update_progress_mock.called)
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(update_service.HPEUpdateService,
|
||||
'get_firmware_update_progress', autospec=True)
|
||||
@mock.patch.object(common, 'wait_for_ilo_after_reset', lambda x: None)
|
||||
def test_wait_for_redfish_firmware_update_to_complete_ok(
|
||||
self, get_firmware_update_progress_mock, sleep_mock):
|
||||
# | GIVEN |
|
||||
get_firmware_update_progress_mock.side_effect = [('Updating', 25),
|
||||
('Complete', None)]
|
||||
# | WHEN |
|
||||
(self.us_inst.
|
||||
wait_for_redfish_firmware_update_to_complete(self.rf_client))
|
||||
# | THEN |
|
||||
self.assertEqual(2, get_firmware_update_progress_mock.call_count)
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(update_service.HPEUpdateService,
|
||||
'get_firmware_update_progress', autospec=True)
|
||||
@mock.patch.object(common, 'wait_for_ilo_after_reset', lambda x: None)
|
||||
def test_wait_for_redfish_firmware_update_to_complete_multiple_retries(
|
||||
self, get_firmware_update_progress_mock, sleep_mock):
|
||||
# | GIVEN |
|
||||
get_firmware_update_progress_mock.side_effect = [('Idle', 0),
|
||||
('Updating', 25),
|
||||
('Updating', 50),
|
||||
('Updating', 75),
|
||||
('Error', 0)]
|
||||
# | WHEN |
|
||||
(self.us_inst.
|
||||
wait_for_redfish_firmware_update_to_complete(self.rf_client))
|
||||
# | THEN |
|
||||
self.assertEqual(5, get_firmware_update_progress_mock.call_count)
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(update_service.HPEUpdateService,
|
||||
'get_firmware_update_progress', autospec=True)
|
||||
@mock.patch.object(common, 'wait_for_ilo_after_reset', lambda x: None)
|
||||
def test_wait_for_redfish_firmware_update_to_complete_retry_on_exception(
|
||||
self, get_firmware_update_progress_mock, sleep_mock):
|
||||
# | GIVEN |
|
||||
exc = exception.IloError('error')
|
||||
get_firmware_update_progress_mock.side_effect = [('Updating', 25),
|
||||
exc,
|
||||
('Complete', None)]
|
||||
# | WHEN |
|
||||
(self.us_inst.
|
||||
wait_for_redfish_firmware_update_to_complete(self.rf_client))
|
||||
# | THEN |
|
||||
self.assertEqual(3, get_firmware_update_progress_mock.call_count)
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(update_service.HPEUpdateService,
|
||||
'get_firmware_update_progress', autospec=True)
|
||||
@mock.patch.object(common, 'wait_for_ilo_after_reset', lambda x: None)
|
||||
def test_wait_for_redfish_firmware_update_to_complete_very_quick_update(
|
||||
self, get_firmware_update_progress_mock, sleep_mock):
|
||||
# | GIVEN |
|
||||
get_firmware_update_progress_mock.side_effect = [('Complete', None)]
|
||||
# | WHEN |
|
||||
(self.us_inst.
|
||||
wait_for_redfish_firmware_update_to_complete(self.rf_client))
|
||||
# | THEN |
|
||||
self.assertEqual(1, get_firmware_update_progress_mock.call_count)
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(update_service.HPEUpdateService,
|
||||
'get_firmware_update_progress', autospec=True)
|
||||
@mock.patch.object(common, 'wait_for_ilo_after_reset', lambda x: None)
|
||||
def test_wait_for_redfish_firmware_update_to_complete_fail(
|
||||
self, get_firmware_update_progress_mock, sleep_mock):
|
||||
# | GIVEN |
|
||||
exc = exception.IloError('error')
|
||||
get_firmware_update_progress_mock.side_effect = exc
|
||||
# | WHEN & THEN|
|
||||
self.assertRaises(exception.IloError,
|
||||
(self.us_inst.
|
||||
wait_for_redfish_firmware_update_to_complete),
|
||||
self.rf_client)
|
||||
self.assertEqual(10, get_firmware_update_progress_mock.call_count)
|
||||
|
||||
@mock.patch.object(update_service.HPEUpdateService, 'refresh',
|
||||
autospec=True)
|
||||
def test_get_firmware_update_progress(self, refresh_mock):
|
||||
refresh_mock.return_value.status_code = 200
|
||||
state, percent = self.us_inst.get_firmware_update_progress()
|
||||
self.assertEqual(('Updating', 24), (state, percent))
|
||||
|
||||
@mock.patch.object(update_service.HPEUpdateService,
|
||||
'refresh', autospec=True)
|
||||
def test_get_firmware_update_progress_refresh_exception(self,
|
||||
refresh_mock):
|
||||
refresh_mock.side_effect = (sushy.exceptions.SushyError)
|
||||
state, percent = self.us_inst.get_firmware_update_progress()
|
||||
self.assertEqual(('Unknown', 'Unknown'), (state, percent))
|
|
@ -23,6 +23,7 @@ from proliantutils import exception
|
|||
from proliantutils.redfish import main
|
||||
from proliantutils.redfish.resources.manager import manager
|
||||
from proliantutils.redfish.resources.system import system
|
||||
from proliantutils.redfish.resources import update_service
|
||||
|
||||
|
||||
class HPESushyTestCase(testtools.TestCase):
|
||||
|
@ -78,3 +79,12 @@ class HPESushyTestCase(testtools.TestCase):
|
|||
mock_manager.assert_called_once_with(self.hpe_sushy._conn,
|
||||
'1234',
|
||||
self.hpe_sushy.redfish_version)
|
||||
|
||||
@mock.patch.object(update_service, 'HPEUpdateService', autospec=True)
|
||||
def test_get_update_service(self, mock_update_service):
|
||||
us_inst = self.hpe_sushy.get_update_service()
|
||||
self.assertIsInstance(us_inst,
|
||||
update_service.HPEUpdateService.__class__)
|
||||
mock_update_service.assert_called_once_with(
|
||||
self.hpe_sushy._conn, "/redfish/v1/UpdateService/",
|
||||
self.hpe_sushy.redfish_version)
|
||||
|
|
|
@ -418,3 +418,23 @@ class RedfishOperationsTestCase(testtools.TestCase):
|
|||
self.rf_client.set_vm_status(device='CDROM', boot_option='CONNECT')
|
||||
self.assertFalse(manager_mock.called)
|
||||
self.assertFalse(set_mock.called)
|
||||
|
||||
def test_update_firmware(self):
|
||||
self.rf_client.update_firmware('fw_file_url', 'ilo')
|
||||
(self.sushy.get_update_service.return_value.flash_firmware.
|
||||
assert_called_once_with(self.rf_client, 'fw_file_url'))
|
||||
|
||||
def test_update_firmware_flash_firmware_fail(self):
|
||||
(self.sushy.get_update_service.return_value.
|
||||
flash_firmware.side_effect) = sushy.exceptions.SushyError
|
||||
self.assertRaisesRegex(
|
||||
exception.IloError,
|
||||
'The Redfish controller failed to update firmware',
|
||||
self.rf_client.update_firmware, 'fw_file_url', 'cpld')
|
||||
|
||||
def test_update_firmware_get_update_service_fail(self):
|
||||
self.sushy.get_update_service.side_effect = sushy.exceptions.SushyError
|
||||
self.assertRaisesRegex(
|
||||
exception.IloError,
|
||||
'The Redfish controller failed to update firmware',
|
||||
self.rf_client.update_firmware, 'fw_file_url', 'cpld')
|
||||
|
|
Loading…
Reference in New Issue