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 2026-08-22 21:36:38
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-sushy (Old)
 and      /work/SRC/openSUSE:Factory/.python-sushy.new.1258 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-sushy"

Sat Aug 22 21:36:38 2026 rev:25 rq:1373088 version:5.13.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-sushy/python-sushy.changes        
2026-08-09 21:37:15.078148215 +0200
+++ /work/SRC/openSUSE:Factory/.python-sushy.new.1258/python-sushy.changes      
2026-08-22 21:38:45.056816164 +0200
@@ -1,0 +2,7 @@
+Sat Aug 22 14:13:41 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 5.13.0:
+  * system: guard HttpBootUri writes against iDRAC 10 removal
+  * Handle incomplete TaskMonitor responses
+
+-------------------------------------------------------------------

Old:
----
  sushy-5.12.0.tar.gz

New:
----
  sushy-5.13.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-sushy.spec ++++++
--- /var/tmp/diff_new_pack.EIMz2k/_old  2026-08-22 21:38:46.397864198 +0200
+++ /var/tmp/diff_new_pack.EIMz2k/_new  2026-08-22 21:38:46.399864269 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           python-sushy
-Version:        5.12.0
+Version:        5.13.0
 Release:        0
 Summary:        Python library to communicate with Redfish based systems
 License:        Apache-2.0

++++++ sushy-5.12.0.tar.gz -> sushy-5.13.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sushy-5.12.0/AUTHORS new/sushy-5.13.0/AUTHORS
--- old/sushy-5.12.0/AUTHORS    2026-08-03 14:37:45.000000000 +0200
+++ new/sushy-5.13.0/AUTHORS    2026-08-20 17:16:13.154013400 +0200
@@ -48,6 +48,7 @@
 Marcus Furlong <[email protected]>
 Mark Goddard <[email protected]>
 Milan Fencik <[email protected]>
+Mohammed Naser <[email protected]>
 Nahian Pathan <[email protected]>
 Nate Potter <[email protected]>
 Nguyen Van Trung <[email protected]>
@@ -74,6 +75,7 @@
 Varsha <[email protected]>
 Vu Cong Tuan <[email protected]>
 Winicius Silva <[email protected]>
+Yorick <[email protected]>
 Youngjun <[email protected]>
 Yusef Shaban <[email protected]>
 ajya <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sushy-5.12.0/ChangeLog new/sushy-5.13.0/ChangeLog
--- old/sushy-5.12.0/ChangeLog  2026-08-03 14:37:45.000000000 +0200
+++ new/sushy-5.13.0/ChangeLog  2026-08-20 17:16:13.098004600 +0200
@@ -1,6 +1,12 @@
 CHANGES
 =======
 
+5.13.0
+------
+
+* system: guard HttpBootUri writes against iDRAC 10 removal
+* Handle incomplete TaskMonitor responses
+
 5.12.0
 ------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sushy-5.12.0/PKG-INFO new/sushy-5.13.0/PKG-INFO
--- old/sushy-5.12.0/PKG-INFO   2026-08-03 14:37:45.465364700 +0200
+++ new/sushy-5.13.0/PKG-INFO   2026-08-20 17:16:13.455060700 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: sushy
-Version: 5.12.0
+Version: 5.13.0
 Summary: Sushy is a small Python library to communicate with Redfish based 
systems
 Home-page: https://docs.openstack.org/sushy/latest/
 Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/sushy-5.12.0/releasenotes/notes/idrac10-httpbooturi-59d970aaf3fe86c2.yaml 
new/sushy-5.13.0/releasenotes/notes/idrac10-httpbooturi-59d970aaf3fe86c2.yaml
--- 
old/sushy-5.12.0/releasenotes/notes/idrac10-httpbooturi-59d970aaf3fe86c2.yaml   
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/sushy-5.13.0/releasenotes/notes/idrac10-httpbooturi-59d970aaf3fe86c2.yaml   
    2026-08-20 17:15:26.821323200 +0200
@@ -0,0 +1,9 @@
+---
+fixes:
+  - |
+    Fixed ``set_system_boot_source`` to handle BMCs that do not advertise
+    ``HttpBootUri`` in the Boot section, such as iDRAC 10 which removed
+    this property entirely. The property is now only written when the BMC
+    explicitly advertises it, preventing spurious 400 errors on UefiHTTP
+    boot requests. An explicit URI passed by the caller will still raise
+    ``MissingAttributeError`` when the BMC does not support the property.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sushy-5.12.0/sushy/resources/system/system.py 
new/sushy-5.13.0/sushy/resources/system/system.py
--- old/sushy-5.12.0/sushy/resources/system/system.py   2026-08-03 
14:36:58.000000000 +0200
+++ new/sushy-5.13.0/sushy/resources/system/system.py   2026-08-20 
17:15:26.882451300 +0200
@@ -349,15 +349,18 @@
             a :py:class:`sushy.BootSourceOverrideMode` value. Optional.
         :param http_boot_uri: The requested HTTP Boot URI to transmit to the
             BMC. Only valid when BootSourceOverrideTarget is set to UefiHTTP,
-            when utilizing the ``target`` parameter. If no value is supplied,
-            and the target is set to UefiHTTP, then an empty value will be
-            sent to the BMC to remove any prior setting, allowing the host
-            to load configuration from DHCP.
+            when utilizing the ``target`` parameter. If no value is supplied
+            and the target is set to UefiHTTP, an existing value is cleared
+            only when the BMC advertises the HttpBootUri property. Otherwise
+            the property is omitted, allowing the host to load configuration
+            from DHCP.
             If not explicitly set, any value will be removed from a BMC when
             UefiHttp boot is not engaged.
 
         :raises: InvalidParameterValueError, if any information passed is
             invalid.
+        :raises: MissingAttributeError, if an explicit HTTP boot URI is
+            requested but the BMC does not advertise HttpBootUri.
         """
         data = collections.defaultdict(dict)
         settings_data = collections.defaultdict(dict)
@@ -369,6 +372,37 @@
             settings_resp = None
             settings_boot_section = {}
 
+        main_boot_section = self.json.get('Boot') or {}
+
+        def _set_boot_property(name, value, require_advertised=False,
+                               only_if_set=False):
+            """Add a Boot property to the correct Redfish resource.
+
+            Prefer the Settings resource when it advertises the property,
+            otherwise use the main ComputerSystem resource. For standard boot
+            properties, preserve the existing fallback to ComputerSystem even
+            when the property is not present in the response. Properties such
+            as HttpBootUri can require explicit advertisement instead.
+
+            :returns: ``True`` when the property is supported or queued,
+                otherwise ``False``.
+            """
+            if settings_resp and name in settings_boot_section:
+                boot_data = settings_data
+                current_value = settings_boot_section.get(name)
+            elif name in main_boot_section:
+                boot_data = data
+                current_value = main_boot_section.get(name)
+            elif require_advertised:
+                return False
+            else:
+                boot_data = data
+                current_value = None
+
+            if not only_if_set or current_value is not None:
+                boot_data['Boot'][name] = value
+            return True
+
         if target is not None:
             valid_targets = self.get_allowed_system_boot_source_values()
             if target not in valid_targets:
@@ -394,12 +428,32 @@
                           'machine. Overriding boot device from %s to %s.',
                           target, sys_cons.BootSource.USB_CD)
                 target = sys_cons.BootSource.USB_CD
-            if (settings_resp and "BootSourceOverrideTarget" in
-                    settings_boot_section):
-                settings_data['Boot']['BootSourceOverrideTarget'] = \
-                    target.value
-            else:
-                data['Boot']['BootSourceOverrideTarget'] = target.value
+            _set_boot_property('BootSourceOverrideTarget', target.value)
+
+            if target == sys_cons.BootSource.UEFI_HTTP:
+                # The http_boot_uri value *can* be set independently of the
+                # target, but the BMC will just ignore it unless the target
+                # is set. So we should only, and explicitly set it when we've
+                # been requested to boot from UefiHTTP.
+                if http_boot_uri:
+                    if not _set_boot_property(
+                            'HttpBootUri', http_boot_uri,
+                            require_advertised=True):
+                        raise exceptions.MissingAttributeError(
+                            attribute='HttpBootUri', resource=self.path)
+                else:
+                    # DHCP-based UEFI HTTP boot. Clear a prior explicit URI
+                    # only when the BMC advertises the property; otherwise
+                    # omit it.
+                    _set_boot_property(
+                        'HttpBootUri', None, require_advertised=True,
+                        only_if_set=True)
+            elif not http_boot_uri:
+                # We're switching to a non-HTTP target. Clear a previous URI
+                # only on the Redfish resource that actually advertises it.
+                _set_boot_property(
+                    'HttpBootUri', None, require_advertised=True,
+                    only_if_set=True)
 
         if enabled is not None:
             try:
@@ -408,11 +462,7 @@
                 raise exceptions.InvalidParameterValueError(
                     parameter='enabled', value=enabled,
                     valid_values=list(sys_cons.BootSourceOverrideEnabled))
-            if (settings_resp and "BootSourceOverrideEnabled" in
-                    settings_boot_section):
-                settings_data['Boot']['BootSourceOverrideEnabled'] = fishy_freq
-            else:
-                data['Boot']['BootSourceOverrideEnabled'] = fishy_freq
+            _set_boot_property('BootSourceOverrideEnabled', fishy_freq)
 
         if mode is not None:
             try:
@@ -421,32 +471,7 @@
                 raise exceptions.InvalidParameterValueError(
                     parameter='mode', value=mode,
                     valid_values=list(sys_cons.BootSourceOverrideMode))
-            if (settings_resp and "BootSourceOverrideMode" in
-                    settings_boot_section):
-                settings_data['Boot']['BootSourceOverrideMode'] = fishy_mode
-            else:
-                data['Boot']['BootSourceOverrideMode'] = fishy_mode
-
-        if target == sys_cons.BootSource.UEFI_HTTP:
-            # The http_boot_uri value *can* be set independently of the
-            # target, but the BMC will just ignore it unless the target
-            # is set. So we should only, and explicitly set it when we've
-            # been requested to boot from UefiHTTP.
-            if not http_boot_uri:
-                # This should clear out any old entries, as no URI translates
-                # to the intent of "use whatever the dhcp server says".
-                http_boot_uri = None
-
-            if (settings_resp and "HttpBootUri" in settings_boot_section):
-                settings_data['Boot']['HttpBootUri'] = http_boot_uri
-            else:
-                data['Boot']['HttpBootUri'] = http_boot_uri
-        elif not http_boot_uri:
-            # We're not doing boot from URL, we should cleanup any setting
-            # which may be from a prior step/call.
-            if settings_boot_section.get('HttpBootUri'):
-                # If the setting is present, and has any value, unset it.
-                data['Boot']['HttpBootUri'] = None
+            _set_boot_property('BootSourceOverrideMode', fishy_mode)
 
         # TODO(lucasagomes): Check the return code and response body ?
         #                    Probably we should call refresh() as well.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sushy-5.12.0/sushy/taskmonitor.py 
new/sushy-5.13.0/sushy/taskmonitor.py
--- old/sushy-5.12.0/sushy/taskmonitor.py       2026-08-03 14:36:58.000000000 
+0200
+++ new/sushy-5.13.0/sushy/taskmonitor.py       2026-08-20 17:15:26.884455700 
+0200
@@ -51,15 +51,30 @@
         self._task = None
         self._response = response
 
-        if (self._response and self._response.content
+        if (self._response
                 and self._response.status_code == http_client.ACCEPTED):
-            self._task = task.Task(self._connector, self._task_monitor_uri,
-                                   redfish_version=self._redfish_version,
-                                   registries=self._registries,
-                                   json_doc=self._response.json())
+            json_doc = self._get_task_json_doc(self._response)
+            if json_doc:
+                self._task = task.Task(
+                    self._connector, self._task_monitor_uri,
+                    redfish_version=self._redfish_version,
+                    registries=self._registries, json_doc=json_doc)
         else:
             self.refresh()
 
+    @staticmethod
+    def _get_task_json_doc(response):
+        """Return a complete Task representation from a monitor response."""
+        if not response.content:
+            return None
+
+        json_doc = response.json()
+        # Some BMCs return partial Task payloads while the monitor remains 202.
+        if not json_doc.get('Id'):
+            return None
+
+        return json_doc
+
     def refresh(self):
         """Refresh the Task
 
@@ -71,19 +86,19 @@
         self._response = self._connector.get(path=self.task_monitor_uri)
 
         if self._response.status_code == http_client.ACCEPTED:
-            # A Task should have been returned, but wasn't
-            if not self._response.content:
+            json_doc = self._get_task_json_doc(self._response)
+            # A complete Task should have been returned, but wasn't.
+            if not json_doc:
                 self._task = None
                 return
 
-            # Assume that the body contains a Task since we got a 202
             if not self._task:
                 self._task = task.Task(self._connector, self._task_monitor_uri,
                                        redfish_version=self._redfish_version,
                                        registries=self._registries,
-                                       json_doc=self._response.json())
+                                       json_doc=json_doc)
             else:
-                self._task.refresh(json_doc=self._response.json())
+                self._task.refresh(json_doc=json_doc)
         else:
             self._task = None
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/sushy-5.12.0/sushy/tests/unit/resources/system/test_system.py 
new/sushy-5.13.0/sushy/tests/unit/resources/system/test_system.py
--- old/sushy-5.12.0/sushy/tests/unit/resources/system/test_system.py   
2026-08-03 14:36:58.000000000 +0200
+++ new/sushy-5.13.0/sushy/tests/unit/resources/system/test_system.py   
2026-08-20 17:15:26.953600600 +0200
@@ -282,7 +282,8 @@
             '/redfish/v1/Systems/437XR1138R2',
             data={'Boot': {'BootSourceOverrideEnabled': 'Continuous',
                            'BootSourceOverrideTarget': 'Pxe',
-                           'BootSourceOverrideMode': 'UEFI'}},
+                           'BootSourceOverrideMode': 'UEFI',
+                           'HttpBootUri': None}},
             etag='81802dbf61beb0bd')
 
     def test_set_system_boot_options_no_mode_specified(self):
@@ -292,7 +293,8 @@
         self.sys_inst._conn.patch.assert_called_once_with(
             '/redfish/v1/Systems/437XR1138R2',
             data={'Boot': {'BootSourceOverrideEnabled': 'Once',
-                           'BootSourceOverrideTarget': 'Hdd'}},
+                           'BootSourceOverrideTarget': 'Hdd',
+                           'HttpBootUri': None}},
             etag='81802dbf61beb0bd')
 
     def test_set_system_boot_options_no_target_specified(self):
@@ -312,7 +314,8 @@
         self.sys_inst._conn.patch.assert_called_once_with(
             '/redfish/v1/Systems/437XR1138R2',
             data={'Boot': {'BootSourceOverrideTarget': 'Pxe',
-                           'BootSourceOverrideMode': 'UEFI'}},
+                           'BootSourceOverrideMode': 'UEFI',
+                           'HttpBootUri': None}},
             etag='81802dbf61beb0bd')
 
     def test_set_system_boot_options_nothing_specified(self):
@@ -346,7 +349,8 @@
         self.sys_inst._conn.patch.assert_called_once_with(
             '/redfish/v1/Systems/437XR1138R2',
             data={'Boot': {'BootSourceOverrideEnabled': 'Once',
-                           'BootSourceOverrideTarget': 'UsbCd'}},
+                           'BootSourceOverrideTarget': 'UsbCd',
+                           'HttpBootUri': None}},
             etag='81802dbf61beb0bd')
 
     def test_set_system_boot_options_supermicro_no_usb_cd_boot(self):
@@ -359,7 +363,8 @@
         self.sys_inst._conn.patch.assert_called_once_with(
             '/redfish/v1/Systems/437XR1138R2',
             data={'Boot': {'BootSourceOverrideEnabled': 'Once',
-                           'BootSourceOverrideTarget': 'Cd'}},
+                           'BootSourceOverrideTarget': 'Cd',
+                           'HttpBootUri': None}},
             etag='81802dbf61beb0bd')
 
     def test_set_system_boot_options_settings_resource_nokia(self):
@@ -444,7 +449,8 @@
         self.sys_inst._conn.patch.assert_called_once_with(
             '/redfish/v1/Systems/1',
             data={'Boot': {'BootSourceOverrideEnabled': 'Once',
-                           'BootSourceOverrideTarget': 'Cd'}},
+                           'BootSourceOverrideTarget': 'Cd',
+                           'HttpBootUri': None}},
             etag='"222"')
 
     def test_set_system_boot_options_settings_resource_bootmode_only(self):
@@ -491,6 +497,18 @@
                            'HttpBootUri': 'http://test.lan/test_image.iso'}},
             etag=mock.ANY)
 
+    def test_set_system_boot_options_httpbooturi_not_advertised(self):
+        self.json_doc['Boot'].pop('HttpBootUri')
+        self.sys_inst._parse_attributes(self.json_doc)
+
+        self.assertRaisesRegex(
+            exceptions.MissingAttributeError,
+            'attribute HttpBootUri',
+            self.sys_inst.set_system_boot_options,
+            sushy.BootSource.UEFI_HTTP,
+            enabled=sushy.BootSourceOverrideEnabled.ONCE,
+            http_boot_uri='http://test.lan/test_image.iso')
+
     def test_set_system_boot_options_httpboot_settings(self):
 
         with open('sushy/tests/unit/json_samples/settings-nokia.json') as f:
@@ -535,25 +553,32 @@
             etag=mock.ANY)
 
     def test_set_system_boot_options_httpboot_unset(self):
+        # When settings advertises HttpBootUri with a value, switching to a
+        # non-HTTP target should clear it on the settings resource, while
+        # writing target/mode to the main system resource.
         self.sys_inst._settings = mock.Mock()
-        self.sys_inst._settings.resource_uri = 'meow'
-        settings_body = json.dumps(
-            {'Boot': {'HttpBootUri': 'http://foo.bar'}}
+        self.sys_inst._settings.resource_uri = (
+            '/redfish/v1/Systems/437XR1138R2/SD'
         )
 
-        get_settings = mock.MagicMock()
-        get_settings.json.return_value = settings_body
-        self.conn.get.side_effect = get_settings
+        get_settings = mock.MagicMock(headers={'ETag': '"abc"'})
+        get_settings.json.return_value = {
+            'Boot': {'HttpBootUri': 'http://foo.bar'}
+        }
+        self.conn.get.return_value = get_settings
 
         self.sys_inst.set_system_boot_options(
             sushy.BootSource.HDD,
             mode=sushy.BootSourceOverrideMode.UEFI
             )
-        self.sys_inst._conn.patch.assert_called_once_with(
+        self.sys_inst._conn.patch.assert_any_call(
+            '/redfish/v1/Systems/437XR1138R2/SD',
+            data={'Boot': {'HttpBootUri': None}},
+            etag='"abc"')
+        self.sys_inst._conn.patch.assert_any_call(
             '/redfish/v1/Systems/437XR1138R2',
             data={'Boot': {'BootSourceOverrideTarget': 'Hdd',
-                           'BootSourceOverrideMode': 'UEFI',
-                           'HttpBootUri': None}},
+                           'BootSourceOverrideMode': 'UEFI'}},
             etag=mock.ANY)
 
     def test_set_system_boot_source(self):
@@ -565,7 +590,8 @@
             '/redfish/v1/Systems/437XR1138R2',
             data={'Boot': {'BootSourceOverrideEnabled': 'Continuous',
                            'BootSourceOverrideTarget': 'Pxe',
-                           'BootSourceOverrideMode': 'UEFI'}},
+                           'BootSourceOverrideMode': 'UEFI',
+                           'HttpBootUri': None}},
             etag='81802dbf61beb0bd')
 
     def test_set_system_boot_source_with_etag(self):
@@ -578,7 +604,8 @@
             '/redfish/v1/Systems/437XR1138R2',
             data={'Boot': {'BootSourceOverrideEnabled': 'Continuous',
                            'BootSourceOverrideTarget': 'Pxe',
-                           'BootSourceOverrideMode': 'UEFI'}},
+                           'BootSourceOverrideMode': 'UEFI',
+                           'HttpBootUri': None}},
             etag="81802dbf61beb0bd")
 
     def test_set_system_boot_source_no_mode_specified(self):
@@ -588,7 +615,8 @@
         self.sys_inst._conn.patch.assert_called_once_with(
             '/redfish/v1/Systems/437XR1138R2',
             data={'Boot': {'BootSourceOverrideEnabled': 'Once',
-                           'BootSourceOverrideTarget': 'Hdd'}},
+                           'BootSourceOverrideTarget': 'Hdd',
+                           'HttpBootUri': None}},
             etag='81802dbf61beb0bd')
 
     def test_set_system_boot_unsets_http_boot_uri(self):
@@ -598,7 +626,8 @@
         self.sys_inst._conn.patch.assert_called_once_with(
             '/redfish/v1/Systems/437XR1138R2',
             data={'Boot': {'BootSourceOverrideEnabled': 'Once',
-                           'BootSourceOverrideTarget': 'Hdd'}},
+                           'BootSourceOverrideTarget': 'Hdd',
+                           'HttpBootUri': None}},
             etag=mock.ANY)
 
     def test_set_system_boot_source_invalid_target(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/sushy-5.12.0/sushy/tests/unit/resources/taskservice/test_task.py 
new/sushy-5.13.0/sushy/tests/unit/resources/taskservice/test_task.py
--- old/sushy-5.12.0/sushy/tests/unit/resources/taskservice/test_task.py        
2026-08-03 14:36:58.000000000 +0200
+++ new/sushy-5.13.0/sushy/tests/unit/resources/taskservice/test_task.py        
2026-08-20 17:15:26.954602700 +0200
@@ -15,6 +15,7 @@
 import json
 from unittest import mock
 
+from sushy import exceptions
 from sushy.resources import constants as res_cons
 from sushy.resources.taskservice import constants as ts_cons
 from sushy.resources.taskservice import task
@@ -61,6 +62,12 @@
         self.assertEqual(res_cons.Severity.WARNING,
                          self.task.messages[0].severity)
 
+    def test_init_missing_identity_raises(self):
+        self.assertRaises(
+            exceptions.MissingAttributeError,
+            task.Task, self.conn, '/redfish/v1/TaskService/Tasks/545',
+            json_doc={'Name': 'Task without identity'})
+
     def test_is_processing_true(self):
         self.task.status_code = http_client.ACCEPTED
         self.assertTrue(self.task.is_processing)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sushy-5.12.0/sushy/tests/unit/test_taskmonitor.py 
new/sushy-5.13.0/sushy/tests/unit/test_taskmonitor.py
--- old/sushy-5.12.0/sushy/tests/unit/test_taskmonitor.py       2026-08-03 
14:36:58.000000000 +0200
+++ new/sushy-5.13.0/sushy/tests/unit/test_taskmonitor.py       2026-08-20 
17:15:26.955604800 +0200
@@ -74,6 +74,20 @@
     def test_init_accepted_content(self):
         self.assertIsNotNone(self.task_monitor.task)
 
+    def test_init_accepted_content_no_task_id(self):
+        response = mock.Mock()
+        response.status_code = http_client.ACCEPTED
+        response.headers = {'Location': '/Task/545'}
+        response.content = b'{"Name": "Test"}'
+        response.json.return_value = {'Name': 'Test'}
+
+        task_monitor = taskmonitor.TaskMonitor(
+            self.conn, '/Task/545', response=response)
+
+        self.assertIsNone(task_monitor.task)
+        self.assertTrue(task_monitor.is_processing)
+        self.assertEqual('/Task/545', task_monitor.task_monitor_uri)
+
     def test_init_no_response(self):
         self.conn.reset_mock()
         self.conn.get.return_value.status_code = 202
@@ -120,6 +134,63 @@
         self.assertEqual(1, self.conn.get.call_count)
         self.assertIsNotNone(self.task_monitor.task)
 
+    def test_refresh_content_no_task_id_no_task(self):
+        self.conn.reset_mock()
+        self.conn.get.return_value.status_code = http_client.ACCEPTED
+        self.conn.get.return_value.headers = {'Content-Length': 42}
+        self.conn.get.return_value.content = b'{"Name": "Test"}'
+        self.conn.get.return_value.json.return_value = {'Name': 'Test'}
+        self.task_monitor._task = None
+
+        self.task_monitor.refresh()
+
+        self.conn.get.assert_called_once_with(path='/Task/545')
+        self.assertIsNone(self.task_monitor.task)
+        self.assertTrue(self.task_monitor.is_processing)
+
+    def test_refresh_content_no_task_id_existing_task(self):
+        self.conn.reset_mock()
+        self.conn.get.return_value.status_code = http_client.ACCEPTED
+        self.conn.get.return_value.headers = {'Content-Length': 42}
+        self.conn.get.return_value.content = b'{"Name": "Test"}'
+        self.conn.get.return_value.json.return_value = {'Name': 'Test'}
+        existing_task = self.task_monitor.task
+
+        with mock.patch.object(existing_task, 'refresh',
+                               autospec=True) as mock_refresh:
+            self.task_monitor.refresh()
+
+        mock_refresh.assert_not_called()
+        self.assertIsNone(self.task_monitor.task)
+
+    def test_refresh_recovers_from_incomplete_task_response(self):
+        response = mock.Mock()
+        response.status_code = http_client.ACCEPTED
+        response.headers = {'Location': '/Task/545'}
+        response.content = b'{"Name": "Test"}'
+        response.json.return_value = {'Name': 'Test'}
+        task_monitor = taskmonitor.TaskMonitor(
+            self.conn, '/Task/545', response=response)
+
+        complete_response = mock.Mock()
+        complete_response.status_code = http_client.ACCEPTED
+        complete_response.headers = {'Content-Length': 42}
+        complete_response.content = json.dumps(self.json_doc).encode('utf-8')
+        complete_response.json.return_value = self.json_doc
+        done_response = mock.Mock()
+        done_response.status_code = http_client.OK
+        self.conn.get.side_effect = [complete_response, done_response]
+
+        task_monitor.refresh()
+
+        self.assertIsNotNone(task_monitor.task)
+        self.assertTrue(task_monitor.is_processing)
+
+        task_monitor.refresh()
+
+        self.assertIsNone(task_monitor.task)
+        self.assertFalse(task_monitor.is_processing)
+
     def test_refresh_done(self):
         self.conn.reset_mock()
         self.conn.get.return_value.status_code = 200
@@ -275,8 +346,8 @@
 
         self.assertIsInstance(tm, taskmonitor.TaskMonitor)
         self.assertEqual('/Task/545', tm.task_monitor_uri)
-        self.assertIsNotNone(tm.task)
-        self.assertEqual('545', tm.task.identity)
+        self.assertIsNone(tm.task)
+        self.assertTrue(tm.is_processing)
 
     def test_from_response_odata_id(self):
         response = mock.Mock()
@@ -295,6 +366,22 @@
         self.assertIsNotNone(tm.task)
         self.assertEqual('545', tm.task.identity)
 
+    def test_from_response_content_no_task_id(self):
+        response = mock.Mock()
+        response.content = b'{"Name": "Test"}'
+        response.json.return_value = {'Name': 'Test'}
+        response.headers = {'Location': '/TaskMonitor/'}
+        response.status_code = http_client.ACCEPTED
+
+        tm = taskmonitor.TaskMonitor.from_response(
+            self.conn, response,
+            '/redfish/v1/UpdateService/Actions/SimpleUpdate')
+
+        self.assertIsInstance(tm, taskmonitor.TaskMonitor)
+        self.assertEqual('/TaskMonitor/', tm.task_monitor_uri)
+        self.assertIsNone(tm.task)
+        self.assertTrue(tm.is_processing)
+
     def test_from_response_location_header_missing(self):
         response = mock.Mock()
         response.content = "something"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sushy-5.12.0/sushy.egg-info/PKG-INFO 
new/sushy-5.13.0/sushy.egg-info/PKG-INFO
--- old/sushy-5.12.0/sushy.egg-info/PKG-INFO    2026-08-03 14:37:45.000000000 
+0200
+++ new/sushy-5.13.0/sushy.egg-info/PKG-INFO    2026-08-20 17:16:13.159014200 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: sushy
-Version: 5.12.0
+Version: 5.13.0
 Summary: Sushy is a small Python library to communicate with Redfish based 
systems
 Home-page: https://docs.openstack.org/sushy/latest/
 Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sushy-5.12.0/sushy.egg-info/SOURCES.txt 
new/sushy-5.13.0/sushy.egg-info/SOURCES.txt
--- old/sushy-5.12.0/sushy.egg-info/SOURCES.txt 2026-08-03 14:37:45.000000000 
+0200
+++ new/sushy-5.13.0/sushy.egg-info/SOURCES.txt 2026-08-20 17:16:13.291035000 
+0200
@@ -132,6 +132,7 @@
 releasenotes/notes/handle_transfer_method-a51d5a17e381ebee.yaml
 releasenotes/notes/health_literals_change-0e3fc0c439b765e3.yaml
 releasenotes/notes/idrac-reset-http-reachability-0998606718098c21.yaml
+releasenotes/notes/idrac10-httpbooturi-59d970aaf3fe86c2.yaml
 releasenotes/notes/idrac10-settings-resource-c18e754c661a7056.yaml
 releasenotes/notes/ignore-empty-string-etags-ee44617d7b0f72ce.yaml
 releasenotes/notes/increase-server-retries-5f11edde8ee0b461.yaml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sushy-5.12.0/sushy.egg-info/pbr.json 
new/sushy-5.13.0/sushy.egg-info/pbr.json
--- old/sushy-5.12.0/sushy.egg-info/pbr.json    2026-08-03 14:37:45.000000000 
+0200
+++ new/sushy-5.13.0/sushy.egg-info/pbr.json    2026-08-20 17:16:13.173016300 
+0200
@@ -1 +1 @@
-{"git_version": "ebc9454", "is_release": true}
\ No newline at end of file
+{"git_version": "f13efd9", "is_release": true}
\ No newline at end of file

Reply via email to