Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-sushy for openSUSE:Factory checked in at 2023-03-07 16:49:39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-sushy (Old) and /work/SRC/openSUSE:Factory/.python-sushy.new.31432 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-sushy" Tue Mar 7 16:49:39 2023 rev:12 rq:1069690 version:4.4.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-sushy/python-sushy.changes 2023-01-05 15:00:54.669038709 +0100 +++ /work/SRC/openSUSE:Factory/.python-sushy.new.31432/python-sushy.changes 2023-03-07 16:50:14.049552939 +0100 @@ -1,0 +2,14 @@ +Mon Mar 6 15:52:38 UTC 2023 - [email protected] + +- update to version 4.4.2 + - Fix exceeding retries + - Fix setting boot related attributes + - workaround: requests verify handling if env is set + - Fix tox4 and setuptools errors + - Remove setuptools workaround + - Handle a different error code for missing TransferProtocolType + - Retry on iDRAC SYS518 errors for all requests + - Handle proper code_status in unit test + - Fix volume deletion on newer iDRACs + +------------------------------------------------------------------- Old: ---- sushy-4.4.0.tar.gz New: ---- sushy-4.4.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-sushy.spec ++++++ --- /var/tmp/diff_new_pack.5Jc9YE/_old 2023-03-07 16:50:14.681556265 +0100 +++ /var/tmp/diff_new_pack.5Jc9YE/_new 2023-03-07 16:50:14.689556307 +0100 @@ -17,13 +17,13 @@ Name: python-sushy -Version: 4.4.0 +Version: 4.4.2 Release: 0 Summary: Python library to communicate with Redfish based systems License: Apache-2.0 Group: Development/Languages/Python URL: https://docs.openstack.org/sushy -Source0: https://files.pythonhosted.org/packages/source/s/sushy/sushy-4.4.0.tar.gz +Source0: https://files.pythonhosted.org/packages/source/s/sushy/sushy-4.4.2.tar.gz BuildRequires: openstack-macros BuildRequires: python3-oslotest BuildRequires: python3-pbr >= 2.0.0 @@ -62,7 +62,7 @@ This package contains the documentation. %prep -%autosetup -p1 -n sushy-4.4.0 +%autosetup -p1 -n sushy-4.4.2 %py_req_cleanup %build @@ -74,7 +74,7 @@ %{py3_install} %check -python3 -m stestr.cli run +%{openstack_stestr_run} %files -n python3-sushy %license LICENSE ++++++ sushy-4.4.0.tar.gz -> sushy-4.4.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/AUTHORS new/sushy-4.4.2/AUTHORS --- old/sushy-4.4.0/AUTHORS 2022-11-22 16:26:19.000000000 +0100 +++ new/sushy-4.4.2/AUTHORS 2023-02-10 17:07:59.000000000 +0100 @@ -27,6 +27,7 @@ Julia Kreger <[email protected]> Kafilat Adeleke <[email protected]> Kaifeng Wang <[email protected]> +Kamlesh Chauvhan <[email protected]> LiZekun <[email protected]> Lin Yang <[email protected]> Lucas Alvares Gomes <[email protected]> @@ -41,6 +42,7 @@ Richard G. Pioso <[email protected]> Richard Pioso <[email protected]> Ruby Loo <[email protected]> +Samuel Kunkel <[email protected]> Sayali Kutwal <[email protected]> Sean McGinnis <[email protected]> Shivanand Tendulker <[email protected]> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/ChangeLog new/sushy-4.4.2/ChangeLog --- old/sushy-4.4.0/ChangeLog 2022-11-22 16:26:18.000000000 +0100 +++ new/sushy-4.4.2/ChangeLog 2023-02-10 17:07:59.000000000 +0100 @@ -1,6 +1,23 @@ CHANGES ======= +4.4.2 +----- + +* workaround: requests verify handling if env is set +* Remove setuptools workaround +* Fix tox4 and setuptools errors +* Fix exceeding retries +* Fix volume deletion on newer iDRACs + +4.4.1 +----- + +* Handle proper code\_status in unit test +* Handle a different error code for missing TransferProtocolType +* Retry on iDRAC SYS518 errors for all requests +* Fix setting boot related attributes + 4.4.0 ----- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/PKG-INFO new/sushy-4.4.2/PKG-INFO --- old/sushy-4.4.0/PKG-INFO 2022-11-22 16:26:19.412175000 +0100 +++ new/sushy-4.4.2/PKG-INFO 2023-02-10 17:08:00.087798600 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: sushy -Version: 4.4.0 +Version: 4.4.2 Summary: Sushy is a small Python library to communicate with Redfish based systems Home-page: https://docs.openstack.org/sushy/latest/ Author: OpenStack @@ -46,4 +46,5 @@ Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 Requires-Python: >=3.6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/releasenotes/notes/check-for-boot-attrs-in-settingsuri-1cad07b6eb1c81b3.yaml new/sushy-4.4.2/releasenotes/notes/check-for-boot-attrs-in-settingsuri-1cad07b6eb1c81b3.yaml --- old/sushy-4.4.0/releasenotes/notes/check-for-boot-attrs-in-settingsuri-1cad07b6eb1c81b3.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/sushy-4.4.2/releasenotes/notes/check-for-boot-attrs-in-settingsuri-1cad07b6eb1c81b3.yaml 2023-02-10 17:07:32.000000000 +0100 @@ -0,0 +1,14 @@ +--- +fixes: + - | + Adds an extra check for cases where the BMC provides a SettingsObject + URI through @Redfish.Settings but this URI does not allow setting boot + related attributes. Prior to sending a PATCH request to SettingsURI, a + GET request is issued to verify if it contains the attributes to be + updated. In case these attributes are missing, the request is made against + System URI instead. + Issues such as the one addressed with this change usually manifest + themselves with a Redfish response containing an error message similar to + the following: ``MessageId: Base.1.8.PropertyNotWritable, Message: The + property BootSourceOverrideEnabled is a read only property and cannot be + assigned a value.`` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/releasenotes/notes/fix-exceeding-retries-663ab543cc14f261.yaml new/sushy-4.4.2/releasenotes/notes/fix-exceeding-retries-663ab543cc14f261.yaml --- old/sushy-4.4.0/releasenotes/notes/fix-exceeding-retries-663ab543cc14f261.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/sushy-4.4.2/releasenotes/notes/fix-exceeding-retries-663ab543cc14f261.yaml 2023-02-10 17:07:32.000000000 +0100 @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixes exceeding retries. Before this fix running sushy for longer it no + longer retried for temporary failures when it should. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/releasenotes/notes/fix-retry_volume_operation-on_sys518-009f2b16e5c38a27.yaml new/sushy-4.4.2/releasenotes/notes/fix-retry_volume_operation-on_sys518-009f2b16e5c38a27.yaml --- old/sushy-4.4.0/releasenotes/notes/fix-retry_volume_operation-on_sys518-009f2b16e5c38a27.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/sushy-4.4.2/releasenotes/notes/fix-retry_volume_operation-on_sys518-009f2b16e5c38a27.yaml 2023-02-10 17:07:32.000000000 +0100 @@ -0,0 +1,8 @@ +--- +fixes: + - | + Add retries on iDRAC error with code SYS518 and message "iDRAC is + currently unable to display any information because data sources are + unavailable." for all request types in addition to existing GET methods. + This helps to fix a known intermittent issue when deleting set of volumes + one after another and iDRAC is reloading after deleting each volume. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/releasenotes/notes/fix-volume-delete-configuration-unsuported-operational_time_property-f53f650d8612a847.yaml new/sushy-4.4.2/releasenotes/notes/fix-volume-delete-configuration-unsuported-operational_time_property-f53f650d8612a847.yaml --- old/sushy-4.4.0/releasenotes/notes/fix-volume-delete-configuration-unsuported-operational_time_property-f53f650d8612a847.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/sushy-4.4.2/releasenotes/notes/fix-volume-delete-configuration-unsuported-operational_time_property-f53f650d8612a847.yaml 2023-02-10 17:07:32.000000000 +0100 @@ -0,0 +1,4 @@ +fixes: + - | + Fixes 'Unsupported parameter name @Redfish.OperationApplyTime' error + on iDRAC firmware version 6.00.02.00 or newer when deleting volumes. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/releasenotes/notes/property-missing-7602c421ec177e9a.yaml new/sushy-4.4.2/releasenotes/notes/property-missing-7602c421ec177e9a.yaml --- old/sushy-4.4.0/releasenotes/notes/property-missing-7602c421ec177e9a.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/sushy-4.4.2/releasenotes/notes/property-missing-7602c421ec177e9a.yaml 2023-02-10 17:07:32.000000000 +0100 @@ -0,0 +1,6 @@ +--- +fixes: + - | + Correctly handles error code ``Base.1.5.PropertyMissing`` when dealing with + hardware that requires ``TransferProtocolType`` for virtual media + operations. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/releasenotes/notes/workaround-sushy-requests-verify-handling-6879c273b651246f.yaml new/sushy-4.4.2/releasenotes/notes/workaround-sushy-requests-verify-handling-6879c273b651246f.yaml --- old/sushy-4.4.0/releasenotes/notes/workaround-sushy-requests-verify-handling-6879c273b651246f.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/sushy-4.4.2/releasenotes/notes/workaround-sushy-requests-verify-handling-6879c273b651246f.yaml 2023-02-10 17:07:32.000000000 +0100 @@ -0,0 +1,9 @@ +--- +fixes: + - | + Workaround for https://github.com/psf/requests/issues/3829 + If the env ``REQUESTS_CA_BUNDLE`` is set the ``requests.Session()`` + ignores the verify parameter. Therefore the verify parameter + is moved directly into the function call of requests. + + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/setup.cfg new/sushy-4.4.2/setup.cfg --- old/sushy-4.4.0/setup.cfg 2022-11-22 16:26:19.412175000 +0100 +++ new/sushy-4.4.2/setup.cfg 2023-02-10 17:08:00.087798600 +0100 @@ -21,6 +21,7 @@ Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 [files] packages = diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy/connector.py new/sushy-4.4.2/sushy/connector.py --- old/sushy-4.4.0/sushy/connector.py 2022-11-22 16:25:52.000000000 +0100 +++ new/sushy-4.4.2/sushy/connector.py 2023-02-10 17:07:32.000000000 +0100 @@ -20,6 +20,7 @@ from urllib import parse as urlparse import requests +from urllib3.exceptions import InsecureRequestWarning from sushy import exceptions from sushy.taskmonitor import TaskMonitor @@ -37,7 +38,6 @@ self._url = url self._verify = verify self._session = requests.Session() - self._session.verify = self._verify self._response_callback = response_callback self._auth = None self._server_side_retries = server_side_retries @@ -68,6 +68,13 @@ 'be removed in the future') self.set_http_basic_auth(username, password) + if not self._verify: + # As the user specifically needs to opt out of certificate + # validation the user is aware of the security implications + # and does not need to be overwhelmed by the urllib3 warnings + requests.packages.urllib3.disable_warnings( + category=InsecureRequestWarning) + def set_auth(self, auth): """Sets the authentication mechanism for our connector.""" self._auth = auth @@ -85,8 +92,18 @@ """Close this connector and the associated HTTP session.""" self._session.close() + def check_retry_on_exception(self, exception_msg): + """Checks whether retry on exception is required.""" + if ('SYS518' in str(exception_msg)): + LOG.debug('iDRAC is not yet ready after previous operation. ' + 'Error: %(err)s', {'err': str(exception_msg)}) + return True + else: + return False + def _op(self, method, path='', data=None, headers=None, blocking=False, - timeout=60, **extra_session_req_kwargs): + timeout=60, server_side_retries_left=None, + **extra_session_req_kwargs): """Generic RESTful request handler. :param method: The HTTP method to be used, e.g: GET, POST, @@ -96,6 +113,8 @@ :param headers: Optional dictionary of headers. :param blocking: Whether to block for asynchronous operations. :param timeout: Max time in seconds to wait for blocking async call. + :param server_side_retries_left: Remaining retries. If not provided + will use limit provided by instance's server_side_retries :param extra_session_req_kwargs: Optional keyword argument to pass requests library arguments which would pass on to requests session object. @@ -103,6 +122,10 @@ :raises: ConnectionError :raises: HTTPError """ + + if server_side_retries_left is None: + server_side_retries_left = self._server_side_retries + url = path if urlparse.urlparse(path).netloc else urlparse.urljoin( self._url, path) headers = headers or {} @@ -124,6 +147,7 @@ try: response = self._session.request(method, url, json=data, headers=headers, + verify=self._verify, **extra_session_req_kwargs) except requests.exceptions.RequestException as e: # Capture any general exception by looking for the parent @@ -181,6 +205,7 @@ response = self._session.request( method, url, json=data, headers=headers, + verify=self._verify, **extra_session_req_kwargs) except exceptions.HTTPError as retry_exc: LOG.error("Failure occured while attempting to retry " @@ -197,17 +222,23 @@ "%s", e.message) raise except exceptions.ServerSideError as e: - if method.lower() != 'get' or self._server_side_retries <= 0: - raise - else: + if ((method.lower() == 'get' + or self.check_retry_on_exception(e.message)) + and server_side_retries_left > 0): LOG.warning('Got server side error %s in response to a ' - 'GET request, retrying after %d seconds', - e, self._server_side_retries) + 'GET request, retrying after %d seconds. Retries ' + 'left %d.', + e, self._server_side_retries_delay, + server_side_retries_left) time.sleep(self._server_side_retries_delay) - self._server_side_retries -= 1 - return self._op(method, path, data=data, headers=headers, - blocking=blocking, timeout=timeout, - **extra_session_req_kwargs) + server_side_retries_left -= 1 + return self._op( + method, path, data=data, headers=headers, + blocking=blocking, timeout=timeout, + server_side_retries_left=server_side_retries_left, + **extra_session_req_kwargs) + else: + raise if blocking and response.status_code == 202: if not response.headers.get('Location'): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy/exceptions.py new/sushy-4.4.2/sushy/exceptions.py --- old/sushy-4.4.0/sushy/exceptions.py 2022-11-22 16:25:52.000000000 +0100 +++ new/sushy-4.4.2/sushy/exceptions.py 2023-02-10 17:07:32.000000000 +0100 @@ -96,6 +96,9 @@ message = ('HTTP %(method)s %(url)s returned code %(code)s. %(error)s ' 'Extended information: %(ext_info)s') + extended_info = None + """Extended information provided in the response.""" + def __init__(self, method, url, response): self.status_code = response.status_code try: @@ -106,17 +109,16 @@ {'method': method, 'url': url, 'code': self.status_code}) error = 'unknown error' - ext_info = 'none' else: self.body = body.get('error', {}) self.code = self.body.get('code', 'Base.1.0.GeneralError') self.detail = self.body.get('message') - ext_info = self.body.get('@Message.ExtendedInfo', [{}]) - message = self._get_most_severe_msg(ext_info) + self.extended_info = self.body.get('@Message.ExtendedInfo') + message = self._get_most_severe_msg(self.extended_info or [{}]) self.detail = message or self.detail error = '%s: %s' % (self.code, self.detail or 'unknown error.') kwargs = {'method': method, 'url': url, 'code': self.status_code, - 'error': error, 'ext_info': ext_info} + 'error': error, 'ext_info': self.extended_info} LOG.debug('HTTP response for %(method)s %(url)s: ' 'status code: %(code)s, error: %(error)s, ' 'extended: %(ext_info)s', kwargs) @@ -132,6 +134,14 @@ if m.get('Severity') == sev: return m.get('Message') + @property + def related_properties(self): + """List of properties related to the error.""" + try: + return self.extended_info[0]['RelatedProperties'] + except (IndexError, KeyError, TypeError): + return [] + class BadRequestError(HTTPError): pass diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy/resources/manager/virtual_media.py new/sushy-4.4.2/sushy/resources/manager/virtual_media.py --- old/sushy-4.4.0/sushy/resources/manager/virtual_media.py 2022-11-22 16:25:52.000000000 +0100 +++ new/sushy-4.4.2/sushy/resources/manager/virtual_media.py 2023-02-10 17:07:32.000000000 +0100 @@ -106,17 +106,16 @@ eject_uri = eject_media.target_uri return eject_uri, use_patch - def is_transfer_protocol_required(self, response=None): + def is_transfer_protocol_required(self, error=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 + return ( + (error.code.endswith(".ActionParameterMissing") + or error.code.endswith(".PropertyMissing")) + and "#/TransferProtocolType" in error.related_properties + ) def insert_media(self, image, inserted=True, write_protected=True, username=None, password=None, transfer_method=None): @@ -177,8 +176,8 @@ # 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): + except exceptions.HTTPError as error: + if self.is_transfer_protocol_required(error): if payload['Image'].startswith('https://'): payload['TransferProtocolType'] = "HTTPS" elif payload['Image'].startswith('http://'): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy/resources/system/storage/volume.py new/sushy-4.4.2/sushy/resources/system/storage/volume.py --- old/sushy-4.4.0/sushy/resources/system/storage/volume.py 2022-11-22 16:25:52.000000000 +0100 +++ new/sushy-4.4.2/sushy/resources/system/storage/volume.py 2023-02-10 17:07:32.000000000 +0100 @@ -136,8 +136,22 @@ if (payload and payload.get(_OAT_PROP) == res_cons.ApplyTime.IMMEDIATE.value): blocking = True - r = self._conn.delete(self._path, data=payload, blocking=blocking, - timeout=timeout) + try: + r = self._conn.delete(self._path, data=payload, + blocking=blocking, timeout=timeout) + except exceptions.ServerSideError as exc: + if (_OAT_PROP in str(exc.message) + and 'SYS029' in str(exc.message)): + LOG.debug('Retry volume delete without %(prop)s for %(path)s ' + 'because got error: %(err)s', + {'prop': _OAT_PROP, + 'path': self._path, + 'err': exc}) + payload.pop(_OAT_PROP) + r = self._conn.delete(self._path, data=payload, + blocking=blocking, timeout=timeout) + else: + raise exc return r def delete(self, payload=None, apply_time=None, timeout=500): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy/resources/system/system.py new/sushy-4.4.2/sushy/resources/system/system.py --- old/sushy-4.4.0/sushy/resources/system/system.py 2022-11-22 16:25:52.000000000 +0100 +++ new/sushy-4.4.2/sushy/resources/system/system.py 2023-02-10 17:07:32.000000000 +0100 @@ -228,6 +228,13 @@ invalid. """ data = collections.defaultdict(dict) + settings_data = collections.defaultdict(dict) + + if self._settings and self._settings.resource_uri: + settings_resp = self._conn.get(self._settings.resource_uri) + settings_boot_section = settings_resp.json().get('Boot', {}) + else: + settings_resp = None if target is not None: valid_targets = self.get_allowed_system_boot_source_values() @@ -253,8 +260,12 @@ 'machine. Overriding boot device from %s to %s.', target, sys_cons.BootSource.USB_CD) target = sys_cons.BootSource.USB_CD - - data['Boot']['BootSourceOverrideTarget'] = target.value + if (settings_resp and "BootSourceOverrideTarget" in + settings_boot_section): + settings_data['Boot']['BootSourceOverrideTarget'] = \ + target.value + else: + data['Boot']['BootSourceOverrideTarget'] = target.value if enabled is not None: try: @@ -263,8 +274,11 @@ raise exceptions.InvalidParameterValueError( parameter='enabled', value=enabled, valid_values=list(sys_cons.BootSourceOverrideEnabled)) - - data['Boot']['BootSourceOverrideEnabled'] = fishy_freq + if (settings_resp and "BootSourceOverrideEnabled" in + settings_boot_section): + settings_data['Boot']['BootSourceOverrideEnabled'] = fishy_freq + else: + data['Boot']['BootSourceOverrideEnabled'] = fishy_freq if mode is not None: try: @@ -273,23 +287,23 @@ raise exceptions.InvalidParameterValueError( parameter='mode', value=mode, valid_values=list(sys_cons.BootSourceOverrideMode)) - - data['Boot']['BootSourceOverrideMode'] = fishy_mode - - etag = self._get_etag() - path = self.path - - # NOTE(janders): checking if @Redfish.Settings are available; if so - # using the URI from the SettingsObject. Also ensuring the ETag URI - # matches in this case (the one above would not be valid for new URI). - if self._settings and self._settings.resource_uri: - path = self._settings.resource_uri - resp = self._conn.get(path) - etag = resp.headers.get('ETag') + if (settings_resp and "BootSourceOverrideMode" in + settings_boot_section): + settings_data['Boot']['BootSourceOverrideMode'] = fishy_mode + else: + data['Boot']['BootSourceOverrideMode'] = fishy_mode # TODO(lucasagomes): Check the return code and response body ? # Probably we should call refresh() as well. - self._conn.patch(path, data=data, etag=etag) + if settings_data.get('Boot'): + etag = settings_resp.headers.get('ETag') + path = self._settings.resource_uri + self._conn.patch(path, data=settings_data, + etag=etag) + if data.get('Boot'): + etag = self._get_etag() + path = self.path + self._conn.patch(path, data=data, etag=etag) # TODO(etingof): we should remove this method, eventually def set_system_boot_source( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy/tests/unit/json_samples/settings-body-bootsourceoverridemode-only.json new/sushy-4.4.2/sushy/tests/unit/json_samples/settings-body-bootsourceoverridemode-only.json --- old/sushy-4.4.0/sushy/tests/unit/json_samples/settings-body-bootsourceoverridemode-only.json 1970-01-01 01:00:00.000000000 +0100 +++ new/sushy-4.4.2/sushy/tests/unit/json_samples/settings-body-bootsourceoverridemode-only.json 2023-02-10 17:07:32.000000000 +0100 @@ -0,0 +1,17 @@ +{ + "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Settings", + "@odata.type": "#ComputerSystem.v1_18_0.ComputerSystem", + "@Redfish.SettingsApplyTime": { + "ApplyTime": "OnReset", + "@odata.type": "#Settings.v1_3_4.PreferredApplyTime" + }, + "AssetTag": null, + "Boot": { + "BootOrder": [], + "BootSourceOverrideMode": null, + "UefiTargetBootSourceOverride": null, + "StopBootOnFault": null + }, + "Id": "System.Embedded.1", + "Name": "System" +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy/tests/unit/json_samples/settings-body-lenovo-se450.json new/sushy-4.4.2/sushy/tests/unit/json_samples/settings-body-lenovo-se450.json --- old/sushy-4.4.0/sushy/tests/unit/json_samples/settings-body-lenovo-se450.json 1970-01-01 01:00:00.000000000 +0100 +++ new/sushy-4.4.2/sushy/tests/unit/json_samples/settings-body-lenovo-se450.json 2023-02-10 17:07:32.000000000 +0100 @@ -0,0 +1,17 @@ +{ + "Description": "ComputerSystem 1 Pending Setting", + "Id": "Pending", + "@odata.type": "#ComputerSystem.v1_11_0.ComputerSystem", + "Boot": { + "BootOrder": [ + "Boot0000", + "Boot0001", + "Boot0002", + "Boot0003", + "Boot0004" + ] + }, + "Name": "Pending", + "@odata.etag": "\"21a8f5383ebb2a1fb41\"", + "@odata.id": "/redfish/v1/Systems/1/Pending" +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy/tests/unit/json_samples/settings-body-nokia.json new/sushy-4.4.2/sushy/tests/unit/json_samples/settings-body-nokia.json --- old/sushy-4.4.0/sushy/tests/unit/json_samples/settings-body-nokia.json 1970-01-01 01:00:00.000000000 +0100 +++ new/sushy-4.4.2/sushy/tests/unit/json_samples/settings-body-nokia.json 2023-02-10 17:07:32.000000000 +0100 @@ -0,0 +1,50 @@ +{ + "@odata.context": "/redfish/v1/$metadata#ComputerSystem.ComputerSystem", + "@odata.etag": "\"1660209630\"", + "@odata.id": "/redfish/v1/Systems/Self/SD", + "@odata.type": "#ComputerSystem.v1_8_0.ComputerSystem", + "AssetTag": "AT18996926771_0101", + "Boot": { + "AliasBootOrder": null, + "BootNext": null, + "BootOrder": [ + "Boot0001", + "Boot0003", + "Boot0002" + ], + "BootOrderPropertySelection": "BootOrder", + "BootSourceOverrideEnabled": "Disabled", + "[email protected]": [ + "Disabled", + "Once", + "Continuous" + ], + "BootSourceOverrideMode": "UEFI", + "[email protected]": [ + "UEFI" + ], + "BootSourceOverrideTarget": "Cd", + "[email protected]": [ + "None", + "Pxe", + "Floppy", + "Cd", + "Usb", + "Hdd", + "BiosSetup", + "Utilities", + "Diags", + "UefiShell", + "UefiTarget", + "SDCard", + "UefiHttp", + "RemoteDrive", + "UefiBootNext" + ], + "UefiTargetBootSourceOverride": "" + }, + "Description": "System Self", + "Id": "Self", + "Name": "System", + "SystemType": "Physical" +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy/tests/unit/json_samples/settings-lenovo-se450.json new/sushy-4.4.2/sushy/tests/unit/json_samples/settings-lenovo-se450.json --- old/sushy-4.4.0/sushy/tests/unit/json_samples/settings-lenovo-se450.json 1970-01-01 01:00:00.000000000 +0100 +++ new/sushy-4.4.2/sushy/tests/unit/json_samples/settings-lenovo-se450.json 2023-02-10 17:07:32.000000000 +0100 @@ -0,0 +1,13 @@ +{ + "@Redfish.Settings": { + "Time": null, + "SupportedApplyTimes": [ + "OnReset" + ], + "Messages": [], + "@odata.type": "#Settings.v1_3_0.Settings", + "SettingsObject": { + "@odata.id": "/redfish/v1/Systems/1/Pending" + } + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy/tests/unit/resources/manager/test_virtual_media.py new/sushy-4.4.2/sushy/tests/unit/resources/manager/test_virtual_media.py --- old/sushy-4.4.0/sushy/tests/unit/resources/manager/test_virtual_media.py 2022-11-22 16:25:52.000000000 +0100 +++ new/sushy-4.4.2/sushy/tests/unit/resources/manager/test_virtual_media.py 2023-02-10 17:07:32.000000000 +0100 @@ -16,8 +16,6 @@ import json from unittest import mock -import requests - import sushy from sushy import exceptions from sushy.resources.certificateservice import certificate @@ -178,18 +176,25 @@ headers={"If-Match": 'W/"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): + def test_is_transfer_protocol_required(self): + with open('sushy/tests/unit/json_samples/' + 'transfer_proto_required_error.json') as f: + response_obj = json.load(f) + response = mock.Mock(spec=['json', 'status_code']) + response.json.return_value = response_obj + error = exceptions.HTTPError('GET', 'VirtualMedia', response) + retval = self.sys_virtual_media.is_transfer_protocol_required(error) + self.assertTrue(retval) + + def test_is_transfer_protocol_required_alt_code(self): 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) + response_obj['error']['code'] = 'Base.1.5.PropertyMissing' + response = mock.Mock(spec=['json', 'status_code']) + response.json.return_value = response_obj + error = exceptions.HTTPError('GET', 'VirtualMedia', response) + retval = self.sys_virtual_media.is_transfer_protocol_required(error) self.assertTrue(retval) def test_eject_media_none(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy/tests/unit/resources/system/storage/test_volume.py new/sushy-4.4.2/sushy/tests/unit/resources/system/storage/test_volume.py --- old/sushy-4.4.0/sushy/tests/unit/resources/system/storage/test_volume.py 2022-11-22 16:25:52.000000000 +0100 +++ new/sushy-4.4.2/sushy/tests/unit/resources/system/storage/test_volume.py 2023-02-10 17:07:32.000000000 +0100 @@ -16,6 +16,7 @@ from dateutil import parser import sushy +from sushy import exceptions from sushy.resources import constants as res_cons from sushy.resources.system.storage import constants as store_cons from sushy.resources.system.storage import volume @@ -106,6 +107,84 @@ self.assertEqual(task_mon.task_monitor_uri, '/redfish/v1/taskmon/4608f7e6') + @mock.patch.object(volume.LOG, 'debug', autospec=True) + def test_delete_retry_on_501_sys029_apply_time(self, mock_debug): + payload = {} + _OAT_PROP = '@Redfish.OperationApplyTime' + payload[_OAT_PROP] = 'Immediate' + target_uri = '/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/1' + response_info = {"error": {"@Message.ExtendedInfo": [ + {'Message': '@Redfish.OperationApplyTime.', + 'MessageId': 'IDRAC.2.7.SYS029'}]}} + mock_error = mock.Mock() + mock_error.status_code = 501 + mock_error.json.return_value = response_info + mock_success = mock.Mock() + mock_success.status_code = 201 + self.conn.delete.side_effect = [exceptions.ServerSideError( + method='DELETE', url=target_uri, response=mock_error), + mock_success] + + resource = self.stor_volume.delete( + payload=payload, apply_time=res_cons.ApplyTime.IMMEDIATE) + + self.assertIsNone(resource) + self.assertEqual(2, self.stor_volume._conn.delete.call_count) + expected_calls = [ + mock.call(self.stor_volume._path, data=payload, blocking=True, + timeout=500), + mock.call(self.stor_volume._path, data={}, blocking=True, + timeout=500) + ] + self.stor_volume._conn.delete.assert_has_calls(expected_calls) + mock_debug.assert_called_once() + + @mock.patch.object(volume.LOG, 'debug', autospec=True) + def test_delete_retry_on_501_sys029_other(self, mock_debug): + payload = {} + _OAT_PROP = '@Redfish.OperationApplyTime' + payload[_OAT_PROP] = 'Immediate' + target_uri = '/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/1' + response_info = {"error": {"@Message.ExtendedInfo": [ + {'Message': '@Redfish.SomethingElse.', + 'MessageId': 'IDRAC.2.7.SYS029'}]}} + mock_error = mock.Mock() + mock_error.status_code = 501 + mock_error.json.return_value = response_info + mock_success = mock.Mock() + mock_success.status_code = 201 + self.conn.delete.side_effect = [exceptions.ServerSideError( + method='DELETE', url=target_uri, response=mock_error), + mock_success] + + self.assertRaises(exceptions.ServerSideError, self.stor_volume.delete, + payload=payload, + apply_time=res_cons.ApplyTime.IMMEDIATE) + self.stor_volume._conn.delete.assert_called_once_with( + self.stor_volume._path, data=payload, blocking=True, timeout=500) + mock_debug.assert_not_called() + + @mock.patch.object(volume.LOG, 'debug', autospec=True) + def test_delete_raise_on_501_other(self, mock_debug): + payload = {} + _OAT_PROP = '@Redfish.OperationApplyTime' + payload[_OAT_PROP] = 'Immediate' + target_uri = '/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/1' + response_info = {"error": {"@Message.ExtendedInfo": [ + {'Message': 'Other message.'}]}} + mock_error = mock.Mock() + mock_error.status_code = 501 + mock_error.json.return_value = response_info + self.conn.delete.side_effect = [exceptions.ServerSideError( + method='DELETE', url=target_uri, response=mock_error)] + + self.assertRaises(exceptions.ServerSideError, self.stor_volume.delete, + payload=payload, + apply_time=res_cons.ApplyTime.IMMEDIATE) + self.stor_volume._conn.delete.assert_called_once_with( + self.stor_volume._path, data=payload, blocking=True, timeout=500) + mock_debug.assert_not_called() + class VolumeCollectionTestCase(base.TestCase): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy/tests/unit/resources/system/test_system.py new/sushy-4.4.2/sushy/tests/unit/resources/system/test_system.py --- old/sushy-4.4.0/sushy/tests/unit/resources/system/test_system.py 2022-11-22 16:25:52.000000000 +0100 +++ new/sushy-4.4.2/sushy/tests/unit/resources/system/test_system.py 2023-02-10 17:07:32.000000000 +0100 @@ -317,9 +317,7 @@ def test_set_system_boot_options_nothing_specified(self): self.sys_inst.set_system_boot_options() - self.sys_inst._conn.patch.assert_called_once_with( - '/redfish/v1/Systems/437XR1138R2', data={}, - etag=None) + self.sys_inst._conn.patch.assert_not_called() def test_set_system_boot_options_invalid_target(self): self.assertRaises(exceptions.InvalidParameterValueError, @@ -366,13 +364,21 @@ etag=None) def test_set_system_boot_options_settings_resource_nokia(self): - self.conn.get.return_value.headers = {'ETag': '"3d7b838291941d"'} with open('sushy/tests/unit/json_samples/settings-nokia.json') as f: settings_obj = json.load(f) self.json_doc.update(settings_obj) self.sys_inst._parse_attributes(self.json_doc) + with open('sushy/tests/unit/json_samples/' + 'settings-body-nokia.json') as f: + settings_body = json.load(f) + + get_settings = mock.MagicMock(headers={'ETag': '"3d7b838291941d"'}) + get_settings.json.return_value = settings_body + get_system = mock.MagicMock(headers={'ETag': '"222"'}) + self.conn.get.side_effect = [get_settings, get_system] + self.sys_inst.set_system_boot_options( target=sushy.BootSource.CD, enabled=sushy.BootSourceOverrideEnabled.ONCE) @@ -384,13 +390,23 @@ etag='"3d7b838291941d"') def test_set_system_boot_options_settings_resource(self): - self.conn.get.return_value.headers = {'ETag': '"3d7b838291941d"'} with open('sushy/tests/unit/json_samples/settings.json') as f: settings_obj = json.load(f) self.json_doc.update(settings_obj) self.sys_inst._parse_attributes(self.json_doc) + with open('sushy/tests/unit/json_samples/' + 'settings-body-nokia.json') as f: + settings_body = json.load(f) + + get_settings = mock.MagicMock(headers={'ETag': '"3d7b838291941d"'}) + get_settings.json.return_value = settings_body + get_system = mock.MagicMock(headers={'ETag': '"222"'}) + self.conn.get.side_effect = [get_settings, get_system] + + self.conn.get.return_value.json.return_value = settings_body + self.sys_inst.set_system_boot_options( target=sushy.BootSource.CD, enabled=sushy.BootSourceOverrideEnabled.ONCE) @@ -401,6 +417,66 @@ 'BootSourceOverrideTarget': 'Cd'}}, etag='"3d7b838291941d"') + def test_set_system_boot_options_settings_resource_lenovo(self): + self.sys_inst = system.System( + self.conn, '/redfish/v1/Systems/1', + redfish_version='1.0.2') + + with open('sushy/tests/unit/json_samples/' + 'settings-lenovo-se450.json') as f: + settings_obj = json.load(f) + + self.json_doc.update(settings_obj) + self.sys_inst._parse_attributes(self.json_doc) + + with open('sushy/tests/unit/json_samples/' + 'settings-body-lenovo-se450.json') as f: + settings_body = json.load(f) + + get_settings = mock.MagicMock(headers={'ETag': '"3d7b838291941d"'}) + get_settings.json.return_value = settings_body + get_system = mock.MagicMock(headers={'ETag': '"222"'}) + self.conn.get.side_effect = [get_settings, get_system] + + self.sys_inst.set_system_boot_options( + target=sushy.BootSource.CD, + enabled=sushy.BootSourceOverrideEnabled.ONCE) + + self.sys_inst._conn.patch.assert_called_once_with( + '/redfish/v1/Systems/1', + data={'Boot': {'BootSourceOverrideEnabled': 'Once', + 'BootSourceOverrideTarget': 'Cd'}}, + etag='"222"') + + def test_set_system_boot_options_settings_resource_bootmode_only(self): + self.sys_inst = system.System( + self.conn, '/redfish/v1/Systems/1', + redfish_version='1.0.2') + + with open('sushy/tests/unit/json_samples/' + 'settings-nokia.json') as f: + settings_obj = json.load(f) + + self.json_doc.update(settings_obj) + self.sys_inst._parse_attributes(self.json_doc) + + with open('sushy/tests/unit/json_samples/' + 'settings-body-bootsourceoverridemode-only.json') as f: + settings_body = json.load(f) + + get_settings = mock.MagicMock(headers={'ETag': '"3d7b838291941d"'}) + get_settings.json.return_value = settings_body + get_system = mock.MagicMock(headers={'ETag': '"222"'}) + self.conn.get.side_effect = [get_settings, get_system] + + self.sys_inst.set_system_boot_options( + mode=sushy.BootSourceOverrideMode.UEFI) + + self.sys_inst._conn.patch.assert_called_with( + '/redfish/v1/Systems/Self/SD', + data={'Boot': {'BootSourceOverrideMode': 'UEFI'}}, + etag='"3d7b838291941d"') + def test_set_system_boot_source(self): self.sys_inst.set_system_boot_source( sushy.BootSource.PXE, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy/tests/unit/test_connector.py new/sushy-4.4.2/sushy/tests/unit/test_connector.py --- old/sushy-4.4.0/sushy/tests/unit/test_connector.py 2022-11-22 16:25:52.000000000 +0100 +++ new/sushy-4.4.2/sushy/tests/unit/test_connector.py 2023-02-10 17:07:32.000000000 +0100 @@ -178,7 +178,7 @@ self.conn._op('GET', path='fake/path', headers=self.headers) self.request.assert_called_once_with( 'GET', 'http://foo.bar:1234/fake/path', - headers=self.headers, json=None) + headers=self.headers, json=None, verify=True) def test_response_callback(self): mock_response_callback = mock.MagicMock() @@ -192,21 +192,22 @@ allow_redirects=False) self.request.assert_called_once_with( 'GET', 'http://foo.bar:1234/fake/path', - headers=self.headers, json=None, allow_redirects=False) + headers=self.headers, json=None, allow_redirects=False, + verify=True) def test_ok_post(self): self.conn._op('POST', path='fake/path', data=self.data.copy(), headers=self.headers) self.request.assert_called_once_with( 'POST', 'http://foo.bar:1234/fake/path', - json=self.data, headers=self.headers) + json=self.data, headers=self.headers, verify=True) def test_ok_put(self): self.conn._op('PUT', path='fake/path', data=self.data.copy(), headers=self.headers) self.request.assert_called_once_with( 'PUT', 'http://foo.bar:1234/fake/path', - json=self.data, headers=self.headers) + json=self.data, headers=self.headers, verify=True) def test_ok_delete(self): expected_headers = self.headers.copy() @@ -214,7 +215,7 @@ self.conn._op('DELETE', path='fake/path', headers=self.headers.copy()) self.request.assert_called_once_with( 'DELETE', 'http://foo.bar:1234/fake/path', - headers=expected_headers, json=None) + headers=expected_headers, json=None, verify=True) def test_ok_post_with_session(self): self.conn._session.headers = {} @@ -226,7 +227,7 @@ data=self.data) self.request.assert_called_once_with( 'POST', 'http://foo.bar:1234/fake/path', - json=self.data, headers=expected_headers) + json=self.data, headers=expected_headers, verify=True) self.assertEqual(self.conn._session.headers, {'X-Auth-Token': 'asdf1234'}) @@ -239,7 +240,7 @@ self.conn._op('GET', path=path, headers=headers) self.request.assert_called_once_with( 'GET', 'http://foo.bar:1234' + path, - headers=expected_headers, json=None) + headers=expected_headers, json=None, verify=True) def test_odata_version_header_redfish_no_headers(self): path = '/redfish/v1/bar' @@ -247,7 +248,7 @@ self.conn._op('GET', path=path) self.request.assert_called_once_with( 'GET', 'http://foo.bar:1234' + path, - headers=expected_headers, json=None) + headers=expected_headers, json=None, verify=True) def test_odata_version_header_redfish_existing_header(self): path = '/redfish/v1/foo' @@ -256,7 +257,7 @@ self.conn._op('GET', path=path, headers=headers) self.request.assert_called_once_with( 'GET', 'http://foo.bar:1234' + path, - headers=expected_headers, json=None) + headers=expected_headers, json=None, verify=True) def test_timed_out_session_unable_to_create_session(self): self.conn._auth.can_refresh_session.return_value = False @@ -362,6 +363,7 @@ self.assertEqual(http_client.BAD_REQUEST, exc.status_code) self.assertIsNotNone(exc.body) self.assertIn('body submitted was malformed JSON', exc.detail) + self.assertEqual(len(exc.extended_info), 3, exc.extended_info) def test_known_http_error_nonlist_ext_info(self): self.request.return_value.status_code =\ @@ -377,6 +379,8 @@ self.assertEqual(http_client.UNSUPPORTED_MEDIA_TYPE, exc.status_code) self.assertIsNotNone(exc.body) self.assertIn('See Resolution for information', exc.detail) + self.assertIn('unsupported media type', + exc.extended_info['Resolution']) @mock.patch('time.sleep', autospec=True) def test_not_found_error(self, mock_sleep): @@ -405,6 +409,42 @@ self.assertEqual(10, mock_sleep.call_count) self.assertEqual(11, self.request.call_count) + @mock.patch('time.sleep', autospec=True) + def test_op_retry_on_server_500_sys518(self, mock_sleep): + response_info = {"error": {"@Message.ExtendedInfo": [ + {'MessageId': 'IDRAC.2.7.SYS518'}]}} + mock_error = mock.Mock() + mock_error.status_code = 500 + mock_error.json.return_value = response_info + self.request.return_value.status_code = ( + http_client.INTERNAL_SERVER_ERROR) + self.request.return_value.json.side_effect =\ + exceptions.ServerSideError( + method='DELETE', url='http://foo.bar', response=mock_error) + + self.assertRaises(exceptions.ServerSideError, self.conn._op, 'DELETE', + 'http://foo.bar') + self.assertEqual(10, mock_sleep.call_count) + self.assertEqual(11, self.request.call_count) + + @mock.patch('time.sleep', autospec=True) + def test_op_retry_on_server_500_other_than_sys518(self, mock_sleep): + response_info = {"error": {"@Message.ExtendedInfo": [ + {'MessageId': 'IDRAC.2.7.SYS999'}]}} + mock_error = mock.Mock() + mock_error.status_code = 500 + mock_error.json.return_value = response_info + self.request.return_value.status_code = ( + http_client.INTERNAL_SERVER_ERROR) + self.request.return_value.json.side_effect =\ + exceptions.ServerSideError( + method='DELETE', url='http://foo.bar', response=mock_error) + + self.assertRaises(exceptions.ServerSideError, self.conn._op, 'DELETE', + 'http://foo.bar') + self.assertEqual(0, mock_sleep.call_count) + self.assertEqual(1, self.request.call_count) + def test_access_error(self): self.conn._auth = None @@ -504,7 +544,7 @@ 'this is expected prior to authentication', 'HTTP GET ' 'http://redfish/v1/SessionService returned code ' '%s. unknown error Extended information: ' - 'none' % http_client.FORBIDDEN) + 'None' % http_client.FORBIDDEN) self.assertEqual(http_client.FORBIDDEN, exc.status_code) def test_blocking_no_location_header(self): @@ -540,10 +580,10 @@ def test_access_error_basic_auth(self, mock_log): self.conn._auth.can_refresh_session.return_value = False self.conn._session.auth = ('foo', 'bar') - self.request.return_value.status_code = http_client.FORBIDDEN + self.request.return_value.status_code = 403 mock_response = mock.Mock() mock_response.json.side_effect = ValueError('no json') - mock_response.status_code = http_client.FORBIDDEN + mock_response.status_code = 403 self.request.return_value.json.side_effect = ValueError('no json') with self.assertRaisesRegex(exceptions.AccessError, @@ -552,12 +592,13 @@ exc = cm.exception self.assertEqual(http_client.FORBIDDEN, exc.status_code) self.conn._auth.authenticate.assert_not_called() + error_msg = (f'HTTP GET http://redfish/v1/SessionService ' + f'returned code {exc.status_code}. unknown error ' + f'Extended information: None') mock_log.assert_called_once_with( "We have encountered an AccessError when using 'basic' " "authentication. %(err)s", - {'err': 'HTTP GET http://redfish/v1/SessionService ' - 'returned code HTTPStatus.FORBIDDEN. unknown error ' - 'Extended information: none'} + {'err': error_msg} ) def test__op_raises_connection_error(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy.egg-info/PKG-INFO new/sushy-4.4.2/sushy.egg-info/PKG-INFO --- old/sushy-4.4.0/sushy.egg-info/PKG-INFO 2022-11-22 16:26:19.000000000 +0100 +++ new/sushy-4.4.2/sushy.egg-info/PKG-INFO 2023-02-10 17:07:59.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: sushy -Version: 4.4.0 +Version: 4.4.2 Summary: Sushy is a small Python library to communicate with Redfish based systems Home-page: https://docs.openstack.org/sushy/latest/ Author: OpenStack @@ -46,4 +46,5 @@ Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 Requires-Python: >=3.6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy.egg-info/SOURCES.txt new/sushy-4.4.2/sushy.egg-info/SOURCES.txt --- old/sushy-4.4.0/sushy.egg-info/SOURCES.txt 2022-11-22 16:26:19.000000000 +0100 +++ new/sushy-4.4.2/sushy.egg-info/SOURCES.txt 2023-02-10 17:07:59.000000000 +0100 @@ -67,6 +67,7 @@ releasenotes/notes/certificate-collection-acc67488c240274c.yaml releasenotes/notes/change-bootdev-smc-ab30317eaf5c37d9.yaml releasenotes/notes/change-vmedia-write-protected-attr-586370a552288801.yaml +releasenotes/notes/check-for-boot-attrs-in-settingsuri-1cad07b6eb1c81b3.yaml releasenotes/notes/config-server-side-retries-d16824019bd709a2.yaml releasenotes/notes/decouple-boot-params-c75e80f5951abb12.yaml releasenotes/notes/deprecate-system-leds-f1a72422c53d281e.yaml @@ -80,6 +81,7 @@ releasenotes/notes/expand-drive-schema-042901f919be646c.yaml releasenotes/notes/fix-2008198-bios-factory-reset-400-bad-request-3f4a7a2aada0835b.yaml releasenotes/notes/fix-eject-media-empty-dict-573b4c9e06f52ce7.yaml +releasenotes/notes/fix-exceeding-retries-663ab543cc14f261.yaml releasenotes/notes/fix-extended-info-error-handling-73fecb6bf5c852ff.yaml releasenotes/notes/fix-insert-media-payload-b5d4c707f81d9603.yaml releasenotes/notes/fix-malformed-boot-mode-1ba1117cad8dcc47.yaml @@ -87,6 +89,7 @@ releasenotes/notes/fix-oem-loading-52da045252b6c33e.yaml releasenotes/notes/fix-refine-resource-refresh-86c21ce230967251.yaml releasenotes/notes/fix-required-oem-attribute-parsing-205e4186275aa293.yaml +releasenotes/notes/fix-retry_volume_operation-on_sys518-009f2b16e5c38a27.yaml releasenotes/notes/fix-return-full-weak-etag-04265472cbea9c0e.yaml releasenotes/notes/fix-simple-storage-device-capacity-bytes-null-0672eed36d9da70a.yaml releasenotes/notes/fix-simple-update-e88838fab4170920.yaml @@ -98,6 +101,7 @@ releasenotes/notes/fix-use-headers-for-options-736940b87c06c189.yaml releasenotes/notes/fix-virtual-media-fallback-15a559414a65c014.yaml releasenotes/notes/fix-volume-actions-not-required-730fd637dd2587ce.yaml +releasenotes/notes/fix-volume-delete-configuration-unsuported-operational_time_property-f53f650d8612a847.yaml releasenotes/notes/fixes-ilo5-redfish-firmware-update-issue-273862b2a11e3536.yaml releasenotes/notes/get-retry-9ca311caf8a0b7bb.yaml releasenotes/notes/handle-basic-auth-access-errors-393b368b31f5cad2.yaml @@ -111,6 +115,7 @@ releasenotes/notes/message-registry-logging-39624ae114c02e15.yaml releasenotes/notes/monitor_firmware_update-664b0c6c1a0307cf.yaml releasenotes/notes/no-passwords-295207ac891d27ab.yaml +releasenotes/notes/property-missing-7602c421ec177e9a.yaml releasenotes/notes/raise-error-on-async-task-failure-b67c7bc189a4d6ca.yaml releasenotes/notes/reauthentication-session-fallback-failure-fixes-4f0dcfdad1afd2d7.yaml releasenotes/notes/redfish-response-log-294f3f10b770e356.yaml @@ -132,6 +137,7 @@ releasenotes/notes/vmedia-1.4.0-9957460fed59d85c.yaml releasenotes/notes/vmedia-certificate-06c367c6ef33d139.yaml releasenotes/notes/vmedia-credentials-14b7705c3c94cc07.yaml +releasenotes/notes/workaround-sushy-requests-verify-handling-6879c273b651246f.yaml releasenotes/source/conf.py releasenotes/source/index.rst releasenotes/source/pike.rst @@ -311,6 +317,10 @@ sushy/tests/unit/json_samples/session_creation_headers_no_location.json sushy/tests/unit/json_samples/session_error.json sushy/tests/unit/json_samples/session_service.json +sushy/tests/unit/json_samples/settings-body-bootsourceoverridemode-only.json +sushy/tests/unit/json_samples/settings-body-lenovo-se450.json +sushy/tests/unit/json_samples/settings-body-nokia.json +sushy/tests/unit/json_samples/settings-lenovo-se450.json sushy/tests/unit/json_samples/settings-nokia.json sushy/tests/unit/json_samples/settings.json sushy/tests/unit/json_samples/simple_storage.json diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/sushy.egg-info/pbr.json new/sushy-4.4.2/sushy.egg-info/pbr.json --- old/sushy-4.4.0/sushy.egg-info/pbr.json 2022-11-22 16:26:19.000000000 +0100 +++ new/sushy-4.4.2/sushy.egg-info/pbr.json 2023-02-10 17:07:59.000000000 +0100 @@ -1 +1 @@ -{"git_version": "56efdee", "is_release": true} \ No newline at end of file +{"git_version": "98c8999", "is_release": true} \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/tox.ini new/sushy-4.4.2/tox.ini --- old/sushy-4.4.0/tox.ini 2022-11-22 16:25:52.000000000 +0100 +++ new/sushy-4.4.2/tox.ini 2023-02-10 17:07:32.000000000 +0100 @@ -1,7 +1,6 @@ [tox] minversion = 3.18.0 envlist = py3,pep8 -skipsdist = True ignore_basepython_conflict=true [testenv] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sushy-4.4.0/zuul.d/project.yaml new/sushy-4.4.2/zuul.d/project.yaml --- old/sushy-4.4.0/zuul.d/project.yaml 2022-11-22 16:25:52.000000000 +0100 +++ new/sushy-4.4.2/zuul.d/project.yaml 2023-02-10 17:07:32.000000000 +0100 @@ -2,7 +2,7 @@ templates: - check-requirements - openstack-cover-jobs - - openstack-python3-antelope-jobs + - openstack-python3-jobs - publish-openstack-docs-pti - release-notes-jobs-python3 check:
