From f13a90c047bc9e395c777ac6a6b92738b4c26d95 Mon Sep 17 00:00:00 2001 From: catborise Date: Mon, 19 Oct 2026 11:39:35 +0300 Subject: [PATCH] fix(storages): a new directory pool starts when its directory does not exist create_storage built only logical pools, so a dir pool whose target path was missing failed to start ("cannot open directory"): the page showed the libvirt error and the pool stayed defined, inactive and without autostart. The pool is now started with VIR_STORAGE_POOL_CREATE_WITH_BUILD, which makes the directory, or for a logical pool the volume group as the separate build call did. A live test creates a dir pool at a missing path on the storages page; the LVM live test still creates its logical pool the same way. --- storages/tests/test_live_pools.py | 53 +++++++++++++++++++++++++++++++ vrtManager/storage.py | 6 ++-- 2 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 storages/tests/test_live_pools.py diff --git a/storages/tests/test_live_pools.py b/storages/tests/test_live_pools.py new file mode 100644 index 00000000..b1127d0b --- /dev/null +++ b/storages/tests/test_live_pools.py @@ -0,0 +1,53 @@ +"""Live check that a directory pool created on the storages page starts +when its directory does not exist yet: libvirt builds it. Runs only with +TEST_LIBVIRT_HOST set.""" + +import os +import unittest + +import libvirt +from computes.models import Compute +from django.contrib.auth import get_user_model +from django.test import TestCase +from django.urls import reverse +from instances.tests import livetest +from vrtManager.connection import connection_manager + +POOL = livetest.PREFIX + "dir" +PATH = f"/var/lib/libvirt/{POOL}" + + +@unittest.skipUnless(livetest.enabled(), "Set TEST_LIBVIRT_HOST to run the live libvirt tests") +class LivePoolsTestCase(TestCase): + def setUp(self): + args = dict( + hostname=os.environ["TEST_LIBVIRT_HOST"], + login=os.environ.get("TEST_LIBVIRT_LOGIN", ""), + password=os.environ.get("TEST_LIBVIRT_PASSWORD", ""), + type=int(os.environ.get("TEST_LIBVIRT_TYPE", 1)), + ) + self.conn = connection_manager.get_connection(*args.values()) + self.remove_pool() + self.addCleanup(self.remove_pool) + self.compute = Compute.objects.create(name="live-pools", **args) + self.client.force_login(get_user_model().objects.create_superuser("live-pools", "lp@example.com", "x")) + + def remove_pool(self): + try: + pool = self.conn.storagePoolLookupByName(POOL) + except libvirt.libvirtError: + return + if pool.isActive(): + pool.destroy() + pool.delete(0) # removes the directory + pool.undefine() + + def test_a_missing_directory_is_built(self): + response = self.client.post( + reverse("storages", args=[self.compute.id]), + {"create": "", "name": POOL, "stg_type": "dir", "target": PATH}, + ) + self.assertRedirects(response, reverse("storage", args=[self.compute.id, POOL]), fetch_redirect_response=False) + pool = self.conn.storagePoolLookupByName(POOL) + self.assertTrue(pool.isActive()) + self.assertTrue(pool.autostart()) diff --git a/vrtManager/storage.py b/vrtManager/storage.py index 517cb2b0..5bab3afb 100644 --- a/vrtManager/storage.py +++ b/vrtManager/storage.py @@ -1,5 +1,6 @@ import contextlib +import libvirt from vrtManager import util from vrtManager.connection import wvmConnect @@ -56,9 +57,8 @@ class wvmStorages(wvmConnect): """ self.define_storage(xml, 0) stg = self.get_storage(name) - if stg_type == "logical": - stg.build(0) - stg.create(0) + # builds the dir pool's directory or the logical pool's volume group + stg.create(libvirt.VIR_STORAGE_POOL_CREATE_WITH_BUILD) stg.setAutostart(1) return stg