Merge "Re-trying InsertMedia call with TransferProtocolType if required"

This commit is contained in:
Zuul 2022-03-02 16:46:50 +00:00 committed by Gerrit Code Review
commit c769149d8c
4 changed files with 70 additions and 1 deletions

View File

@ -0,0 +1,7 @@
---
fixes:
- |
Resolved virtualmedia attach failures caused by the lack of
TransferProtocolType parameter in the request payload which is required
by certain BMCs (e.g. on Nokia servers). This is done by adding capability
to retry virtualmedia InsertMedia with the updated payload in such cases.

View File

@ -106,6 +106,18 @@ class VirtualMedia(base.ResourceBase):
eject_uri = eject_media.target_uri
return eject_uri, use_patch
def is_transfer_protocol_required(self, response=None):
"""Check the response code and body and in case of failure
Try to determine if it happened due to missing TransferProtocolType.
"""
if (response.code == "Base.1.5.ActionParameterMissing"
and response.body is not None):
if ("#/TransferProtocolType" in response.body
["@Message.ExtendedInfo"][0]['RelatedProperties']):
return True
return False
def insert_media(self, image, inserted=True, write_protected=True,
username=None, password=None, transfer_method=None):
"""Attach remote media to virtual media
@ -161,7 +173,19 @@ class VirtualMedia(base.ResourceBase):
payload['Inserted'] = False
if not write_protected:
payload['WriteProtected'] = False
self._conn.post(target_uri, data=payload)
# NOTE(janders) attempting to detect whether attachment failure is
# due to absence of TransferProtocolType param and if so adding it
try:
self._conn.post(target_uri, data=payload)
except exceptions.HTTPError as response:
if self.is_transfer_protocol_required(response):
if payload['Image'].startswith('https://'):
payload['TransferProtocolType'] = "HTTPS"
elif payload['Image'].startswith('http://'):
payload['TransferProtocolType'] = "HTTP"
self._conn.post(target_uri, data=payload)
else:
raise
self.invalidate()
def eject_media(self):

View File

@ -0,0 +1,22 @@
{
"error": {
"@Message.ExtendedInfo": [
{
"@odata.type": "#Message.v1_0_8.Message",
"Message": "The action /redfish/v1/Managers/Self/VirtualMedia/CD1/Actions/VirtualMedia.InsertMedia requires the parameter TransferProtocolType to be present in the request body.",
"MessageArgs": [
"/redfish/v1/Managers/Self/VirtualMedia/CD1/Actions/VirtualMedia.InsertMedia",
"TransferProtocolType"
],
"MessageId": "Base.1.5.ActionParameterMissing",
"RelatedProperties": [
"#/TransferProtocolType"
],
"Resolution": "Supply the action with the required parameter in the request body when the request is resubmitted.",
"Severity": "Critical"
}
],
"code": "Base.1.5.ActionParameterMissing",
"message": "The action /redfish/v1/Managers/Self/VirtualMedia/CD1/Actions/VirtualMedia.InsertMedia requires the parameter TransferProtocolType to be present in the request body."
}
}

View File

@ -16,6 +16,8 @@ from http import client as http_client
import json
from unittest import mock
import requests
import sushy
from sushy import exceptions
from sushy.resources.certificateservice import certificate
@ -176,6 +178,20 @@ class VirtualMediaTestCase(base.TestCase):
headers={"If-Match": 'W/"3d7b8a7360bf2941d","3d7b8a7360bf2941d"'})
self.assertTrue(self.sys_virtual_media._is_stale)
@mock.patch.object(requests, 'post', autospec=True)
def test_is_transfer_protocol_required(self, mock_post):
with open('sushy/tests/unit/json_samples/'
'transfer_proto_required_error.json') as f:
response_obj = json.load(f)
response = mock.MagicMock()
response.status_code = 400
response.code = "Base.1.5.ActionParameterMissing"
response.body = response_obj['error']
response.raise_for_status.side_effect = requests.exceptions.HTTPError
mock_post.return_value = response
retval = self.sys_virtual_media.is_transfer_protocol_required(response)
self.assertTrue(retval)
def test_eject_media_none(self):
self.sys_virtual_media._actions.eject_media = None
self.assertRaisesRegex(