diff --git a/CHANGES.rst b/CHANGES.rst index 51d64604c5..a7f31231c0 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -89,6 +89,12 @@ Compute Storage ~~~~~~~ +- [Local Storage] Fix upload errors being suppressed when locking is disabled + with ``ex_use_locking=False``. The original exception now propagates instead + of the upload appearing to succeed. + (#2204) + [@JunaidAhamed-7777] + - [Local Storage] Release the thread lock if IPC lock acquisition fails, allowing the same lock object to be reused after a timeout or error. (#2203) diff --git a/libcloud/storage/drivers/local.py b/libcloud/storage/drivers/local.py index cd01e1a158..d0f0547c0e 100644 --- a/libcloud/storage/drivers/local.py +++ b/libcloud/storage/drivers/local.py @@ -59,7 +59,7 @@ def __enter__(self): return True def __exit__(self, type, value, traceback): - return value + return False class LockLocalStorage: diff --git a/libcloud/test/storage/test_local.py b/libcloud/test/storage/test_local.py index ae4e060e3f..c0b7a64c8c 100644 --- a/libcloud/test/storage/test_local.py +++ b/libcloud/test/storage/test_local.py @@ -254,6 +254,37 @@ def test_objects_success(self): container.delete() self.remove_tmp_file(tmppath) + def test_upload_object_via_stream_without_locking_propagates_error(self): + driver = LocalStorageDriver(self.key, ex_use_locking=False) + container = driver.create_container("failed-stream") + error = OSError("source stream failed") + + def failing_stream(): + yield b"partial data" + raise error + + with self.assertRaises(OSError) as raised: + driver.upload_object_via_stream(failing_stream(), container, "object") + + self.assertIs(raised.exception, error) + + def test_upload_object_without_locking_propagates_copy_error(self): + driver = LocalStorageDriver(self.key, ex_use_locking=False) + container = driver.create_container("failed-copy") + driver.upload_object_via_stream(iter([b"original"]), container, "object") + missing_source = os.path.join(self.key, "missing-source") + + with self.assertRaises(FileNotFoundError): + driver.upload_object(missing_source, container, "object") + + def test_upload_object_via_stream_without_locking_success(self): + driver = LocalStorageDriver(self.key, ex_use_locking=False) + container = driver.create_container("successful-stream") + obj = driver.upload_object_via_stream(iter([b"first", b"second"]), container, "object") + + self.assertEqual(obj.size, 11) + self.assertEqual(b"".join(driver.download_object_as_stream(obj)), b"firstsecond") + def test_get_container_doesnt_exist(self): try: self.driver.get_container(container_name="container1")