diff --git a/changelogs/fragments/8003-redfish-get-update-status-empty-response.yml b/changelogs/fragments/8003-redfish-get-update-status-empty-response.yml new file mode 100644 index 0000000000..21796e7a0e --- /dev/null +++ b/changelogs/fragments/8003-redfish-get-update-status-empty-response.yml @@ -0,0 +1,2 @@ +bugfixes: + - redfish_info - allow for a GET operation invoked by ``GetUpdateStatus`` to allow for an empty response body for cases where a service returns 204 No Content (https://github.com/ansible-collections/community.general/issues/8003). diff --git a/plugins/module_utils/redfish_utils.py b/plugins/module_utils/redfish_utils.py index 262b2774d2..2fbb7eb798 100644 --- a/plugins/module_utils/redfish_utils.py +++ b/plugins/module_utils/redfish_utils.py @@ -20,6 +20,8 @@ from ansible.module_utils.six import text_type from ansible.module_utils.six.moves import http_client from ansible.module_utils.six.moves.urllib.error import URLError, HTTPError from ansible.module_utils.six.moves.urllib.parse import urlparse +from ansible.module_utils.ansible_release import __version__ as ansible_version +from ansible_collections.community.general.plugins.module_utils.version import LooseVersion GET_HEADERS = {'accept': 'application/json', 'OData-Version': '4.0'} POST_HEADERS = {'content-type': 'application/json', 'accept': 'application/json', @@ -130,7 +132,7 @@ class RedfishUtils(object): return resp # The following functions are to send GET/POST/PATCH/DELETE requests - def get_request(self, uri, override_headers=None): + def get_request(self, uri, override_headers=None, allow_no_resp=False): req_headers = dict(GET_HEADERS) if override_headers: req_headers.update(override_headers) @@ -145,13 +147,19 @@ class RedfishUtils(object): force_basic_auth=basic_auth, validate_certs=False, follow_redirects='all', use_proxy=True, timeout=self.timeout) - if override_headers: - resp = gzip.open(BytesIO(resp.read()), 'rt', encoding='utf-8') - data = json.loads(to_native(resp.read())) - headers = req_headers - else: - data = json.loads(to_native(resp.read())) - headers = dict((k.lower(), v) for (k, v) in resp.info().items()) + headers = dict((k.lower(), v) for (k, v) in resp.info().items()) + try: + if headers.get('content-encoding') == 'gzip' and LooseVersion(ansible_version) < LooseVersion('2.14'): + # Older versions of Ansible do not automatically decompress the data + # Starting in 2.14, open_url will decompress the response data by default + data = json.loads(to_native(gzip.open(BytesIO(resp.read()), 'rt', encoding='utf-8').read())) + else: + data = json.loads(to_native(resp.read())) + except Exception as e: + # No response data; this is okay in certain cases + data = None + if not allow_no_resp: + raise except HTTPError as e: msg = self._get_extended_message(e) return {'ret': False, @@ -1813,7 +1821,7 @@ class RedfishUtils(object): return {'ret': False, 'msg': 'Must provide a handle tracking the update.'} # Get the task or job tracking the update - response = self.get_request(self.root_uri + update_handle) + response = self.get_request(self.root_uri + update_handle, allow_no_resp=True) if response['ret'] is False: return response