Merge "Wait for BIOS configuration job to complete"

This commit is contained in:
Zuul 2024-04-23 13:45:23 +00:00 committed by Gerrit Code Review
commit 4e51aefa3e
5 changed files with 139 additions and 3 deletions

View File

@ -238,8 +238,8 @@ VFDD\
return response
except (sushy.exceptions.ServerSideError,
sushy.exceptions.BadRequestError) as exc:
except sushy.exceptions.HTTPError as exc:
LOG.warning(
'Dell OEM set boot device failed (attempts left '
'%d): %s', attempts, exc)
@ -247,6 +247,8 @@ VFDD\
errors = exc.body and exc.body.get(
'@Message.ExtendedInfo') or []
found = False
for error in errors:
message_id = error.get('MessageId')
@ -254,6 +256,7 @@ VFDD\
error.get('Message', 'Unknown error'))
if constants.IDRAC_CONFIG_PENDING in message_id:
found = True
if not rebooted:
LOG.warning(
'Let\'s try to turn it off and on again... '
@ -264,10 +267,14 @@ VFDD\
break
elif constants.IDRAC_JOB_RUNNING in message_id:
found = True
pass
else:
time.sleep(self.RETRY_DELAY)
if found:
time.sleep(self.RETRY_DELAY)
else:
raise
if not attempts:
LOG.error('Too many (%d) retries, bailing '

View File

@ -0,0 +1,18 @@
{
"error": {
"@Message.ExtendedInfo": [
{
"Message": "Unable to perform the import or export operation because there are pending attribute changes or a configuration job is in progress.",
"MessageArgs": "[]",
"MessageArgs@odata.count": 0,
"MessageId": "IDRAC.2.8.LC068",
"RelatedProperties": [],
"RelatedProperties@odata.count": 0,
"Resolution": "Apply or cancel any pending attribute changes. Changes can be applied by creating a targeted configuration job, or the changes can be cancelled by invoking the DeletePendingConfiguration method. If a configuration job is in progress, wait until it is completed before retrying the import or export system configuration operation.",
"Severity": "Warning"
}
],
"code": "IDRAC.2.8.LC068",
"message": "Unable to perform the import or export operation because there are pending attribute changes or a configuration job is in progress."
}
}

View File

@ -0,0 +1,18 @@
{
"error": {
"@Message.ExtendedInfo": [
{
"Message": "A job operation is already running. Retry the operation after the existing job is completed.",
"MessageArgs": "[]",
"MessageArgs@odata.count": 0,
"MessageId": "IDRAC.2.8.RAC0679",
"RelatedProperties": [],
"RelatedProperties@odata.count": 0,
"Resolution": "Wait until the running job is completed or delete the scheduled job and retry the operation",
"Severity": "Warning"
}
],
"code": "IDRAC.2.8.RAC0679",
"message": "Wait until the running job is completed or delete the scheduled job and retry the operation."
}
}

View File

@ -0,0 +1,6 @@
---
fixes:
- |
Resolves the issue where wait for Lifecycle Controller job ends prematurely
due to iDRAC BMC raising a different exception type than the code
previously expected by using the correct exception class.

View File

@ -14,10 +14,12 @@
# License for the specific language governing permissions and limitations
# under the License.
from http import client as http_client
import json
from unittest import mock
from oslotest.base import BaseTestCase
import requests
import sushy
from sushy.resources.manager import manager
from sushy.taskmonitor import TaskMonitor
@ -94,6 +96,91 @@ class ManagerTestCase(BaseTestCase):
'#FirstBootDevice">VCD-DVD</Attribute></Component>'
'</SystemConfiguration>'})
@mock.patch('time.sleep', autospec=True)
@mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {})
def test_set_virtual_boot_device_cd_running_exc(self, mock_sleep):
oem = self.manager.get_oem_extension('Dell')
with open('sushy_oem_idrac/tests/unit/json_samples/'
'error_running_job.json') as f:
response_obj = json.load(f)
response1 = mock.MagicMock(spec=requests.Response)
response1.status_code = http_client.BAD_REQUEST
response1.json.return_value = response_obj
response1.code = "IDRAC.2.8.LC068"
response2 = mock.MagicMock(spec=requests.Response)
response2.status_code = http_client.OK
self.conn.post.side_effect = [sushy.exceptions.HTTPError(
method='POST', url=self.manager.path, response=response1),
response2]
oem.set_virtual_boot_device(
sushy.VIRTUAL_MEDIA_CD, manager=self.manager)
self.conn.post.assert_called_with(
'/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager'
'.ImportSystemConfiguration',
data={'ShareParameters': {'Target': 'ALL'},
'ImportBuffer':
'<SystemConfiguration><Component FQDD="iDRAC.Embedded.1">'
'<Attribute Name="ServerBoot.1#BootOnce">Enabled'
'</Attribute><Attribute Name="ServerBoot.1'
'#FirstBootDevice">VCD-DVD</Attribute></Component>'
'</SystemConfiguration>'})
@mock.patch('sushy_oem_idrac.utils.reboot_system', autospec=True)
@mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {})
def test_set_virtual_boot_device_cd_pending_exc(self, mock_reboot):
oem = self.manager.get_oem_extension('Dell')
with open('sushy_oem_idrac/tests/unit/json_samples/'
'error_pending_job.json') as f:
response_obj = json.load(f)
response1 = mock.MagicMock(spec=requests.Response)
response1.status_code = http_client.BAD_REQUEST
response1.json.return_value = response_obj
response1.code = "IDRAC.2.8.LC068"
response2 = mock.MagicMock(spec=requests.Response)
response2.status_code = http_client.OK
self.conn.post.side_effect = [sushy.exceptions.HTTPError(
method='POST', url=self.manager.path, response=response1),
response2]
oem.set_virtual_boot_device(
sushy.VIRTUAL_MEDIA_CD, manager=self.manager)
self.conn.post.assert_called_with(
'/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager'
'.ImportSystemConfiguration',
data={'ShareParameters': {'Target': 'ALL'},
'ImportBuffer':
'<SystemConfiguration><Component FQDD="iDRAC.Embedded.1">'
'<Attribute Name="ServerBoot.1#BootOnce">Enabled'
'</Attribute><Attribute Name="ServerBoot.1'
'#FirstBootDevice">VCD-DVD</Attribute></Component>'
'</SystemConfiguration>'})
@mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {})
def test_set_virtual_boot_device_cd_other_exc(self):
oem = self.manager.get_oem_extension('Dell')
response = mock.MagicMock(spec=requests.Response)
response.status_code = http_client.FORBIDDEN
self.conn.post.side_effect = sushy.exceptions.HTTPError(
method='POST', url=self.manager.path, response=response)
self.assertRaises(sushy.exceptions.HTTPError,
oem.set_virtual_boot_device,
sushy.VIRTUAL_MEDIA_CD,
manager=self.manager)
@mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {})
def test_get_allowed_export_target_values(self):
oem = self.manager.get_oem_extension('Dell')