diff --git a/vrtManager/connection.py b/vrtManager/connection.py
index 91032870..6eb7349e 100644
--- a/vrtManager/connection.py
+++ b/vrtManager/connection.py
@@ -1040,12 +1040,13 @@ class wvmConnect(object):
stream, which every connection type carries. A failed write leaves
no volume."""
stream = self.wvm.newStream(0)
- vol = pool.createXML(
- f"{util.xml_escape(name)}{len(data)}"
- "",
- 0,
- )
+ vol = None
try:
+ vol = pool.createXML(
+ f"{util.xml_escape(name)}{len(data)}"
+ "",
+ 0,
+ )
vol.upload(stream, 0, len(data), 0)
stream.sendAll(lambda _stream, size, buffer: buffer.read(size), io.BytesIO(data))
stream.finish()
@@ -1053,7 +1054,8 @@ class wvmConnect(object):
# libvirt: a stream that did not finish is aborted before it is freed
with contextlib.suppress(libvirtError):
stream.abort()
- vol.delete(0)
+ if vol is not None:
+ vol.delete(0)
raise
return vol
diff --git a/vrtManager/tests/test_cloud_init_seed.py b/vrtManager/tests/test_cloud_init_seed.py
index 6717655b..13b8dfbe 100644
--- a/vrtManager/tests/test_cloud_init_seed.py
+++ b/vrtManager/tests/test_cloud_init_seed.py
@@ -81,6 +81,16 @@ class UploadVolumeTestCase(unittest.TestCase):
conn.wvm.newStream.return_value.abort.assert_called_once_with()
+ def test_a_volume_that_cannot_be_made_aborts_the_stream(self):
+ conn = wvmConnect.__new__(wvmConnect)
+ conn.wvm = MagicMock()
+ pool = MagicMock()
+ pool.createXML.side_effect = libvirtError("pool is full")
+ with self.assertRaises(libvirtError):
+ conn.upload_volume(pool, "a.iso", b"data")
+ conn.wvm.newStream.return_value.abort.assert_called_once_with()
+
+
class DeleteWithDisksTestCase(unittest.TestCase):
def vm(self, seed_in_pool=True):
from vrtManager.instance import wvmInstance