Fix GET HTTP 202 status without Location

When a GET request is performed on an asynchronous operation task
monitor URI, the iDRAC service can correctly return the HTTP '202
Accepted' status code without a 'Location' header. [1] This has been
observed while querying the status of the long-running OEM Server
Configuration Profile (SCP) import and export system configuration
operations. [2]

sushy-oem-idrac has incorrectly required the 'Location' header to
continue to query the status of the operation, and determine when it has
completed and whether it succeeded. This fixes that by reusing the URI
provided in the 'Location' header of the response to a previous request,
instead of failing.

[1] http://redfish.dmtf.org/schemas/DSP0266_1.11.0.html#asynchronous-operations
[2] Pushkala Iyer et al., "Server Cloning with Server Configuration
Profiles", (Dell Inc., version 1.1, July 2016),
https://downloads.dell.com/solutions/dell-management-solution-resources/Server
Cloning with Server Configuration Profiles 1_1 Final.pdf.

Co-Authored-By: Derek Higgins <derekh@redhat.com>
Story: 2007640
Task: 39697
Change-Id: I07eef4bab7285d2c454a6112a43b0725e8ee5a09
This commit is contained in:
Richard Pioso 2020-05-07 22:32:46 -04:00
parent 71050eaca6
commit 9915d8e16d
2 changed files with 57 additions and 1 deletions

View File

@ -42,8 +42,9 @@ def http_call(conn, method, *args, **kwargs):
LOG.debug('Finished HTTP %s with args %s %s, response is '
'%d', method, args or '', kwargs, response.status_code)
location = None
while response.status_code == 202:
location = response.headers.get('location')
location = response.headers.get('location', location)
if not location:
raise sushy.exceptions.ExtensionError(
error='Response %d to HTTP %s with args %s, kwargs %s '

View File

@ -0,0 +1,55 @@
# Copyright (c) 2020 Dell Inc. or its subsidiaries.
#
# 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.
from unittest import mock
from oslotest.base import BaseTestCase
import sushy
from sushy_oem_idrac.asynchronous import http_call
class AsychronousTestCase(BaseTestCase):
def setUp(self):
super(AsychronousTestCase, self).setUp()
self.conn = mock.Mock()
def test_http_call_post_accepted(self):
mock_post_response = self.conn.post.return_value
mock_post_response.status_code = 202
mock_post_response.headers.get.return_value = '1'
mock_get_202_response = mock.Mock()
mock_get_202_response.status_code = 202
mock_get_202_response.headers.get.return_value = '1'
mock_get_200_response = mock.Mock()
mock_get_200_response.status_code = 200
self.conn.get.side_effect = [
mock_get_202_response, mock_get_200_response]
resp = http_call(self.conn, 'POST')
self.assertIs(resp, mock_get_200_response)
def test_http_call_post_accepted_no_location(self):
mock_response = self.conn.post.return_value
mock_response.status_code = 202
mock_response.headers.get.return_value = None
self.assertRaises(sushy.exceptions.ExtensionError,
http_call, self.conn, 'POST')