From ef1faf57c8ac45ef6ff4ec7b6b90b112a4b4e770 Mon Sep 17 00:00:00 2001 From: catborise Date: Wed, 21 Oct 2026 21:38:34 +0300 Subject: [PATCH] fix(storages): an unexpected ISO upload failure is logged The upload view sent the error of an unexpected failure to the browser but left nothing in the server log, so whoever runs the server had no trace of it. It is logged with its traceback now; the superuser still sees the message. Co-Authored-By: Claude Opus 5.5 (1M context) --- storages/tests/test_upload_job.py | 7 +++++++ storages/views.py | 3 +++ 2 files changed, 10 insertions(+) diff --git a/storages/tests/test_upload_job.py b/storages/tests/test_upload_job.py index a589aad9..3cc2314d 100644 --- a/storages/tests/test_upload_job.py +++ b/storages/tests/test_upload_job.py @@ -644,6 +644,13 @@ class UploadViewTests(LocalPool, UploadTestCase): response = self.post() self.assertEqual((response.status_code, response.json()["error"]), (400, "ISO image already exists")) + def test_an_unexpected_failure_is_logged(self): + with patch("storages.views.write_chunk", side_effect=OSError("disk gone")), \ + self.assertLogs("storages.views", "ERROR") as logs: + response = self.post() + self.assertEqual((response.status_code, response.json()["error"]), (500, "disk gone")) + self.assertIn("OSError: disk gone", logs.output[0]) + def test_a_busy_session_is_retried(self): self.post(0, total=2, size="6") claims.admit({f"upload:{self.job().pk}": Claim.EXCLUSIVE}, holder="192.0.2.30:1:1") diff --git a/storages/views.py b/storages/views.py index cf9a69e9..210faf94 100644 --- a/storages/views.py +++ b/storages/views.py @@ -1,3 +1,5 @@ +import logging + from admin.decorators import superuser_only from appsettings.settings import app_settings from computes.models import Compute @@ -49,6 +51,7 @@ def _handle_iso_upload(request, conn, compute, pool): except (ValueError, jobs.SubmissionConflict, OperationError) as e: return JsonResponse({"error": str(e)}, status=400) except Exception as e: + logging.getLogger(__name__).exception("ISO upload chunk failed") return JsonResponse({"error": str(e)}, status=500) return JsonResponse({"success": True, "job": str(op.pk)})