mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 19:26:48 +00:00
131 test modules sat next to the code they test; instances alone had 51 of them beside views.py and utils.py. They move into a tests/ package per app, and the JavaScript checks into webvirtcloud/tests/js. Each non-empty tests.py becomes tests/test_views.py; the empty generated stubs are removed. Imports of the app's own modules become absolute, paths built from __file__ go one level up, the live helper is instances.tests.livetest, and coverage omits */tests/*. The suite discovers the same 960 tests as before.
117 lines
4.6 KiB
Python
117 lines
4.6 KiB
Python
"""Live checks for cloning. Runs only with TEST_LIBVIRT_HOST set."""
|
|
|
|
import os
|
|
import unittest
|
|
from xml.etree import ElementTree
|
|
|
|
import libvirt
|
|
from django.test import SimpleTestCase
|
|
from vrtManager.connection import connection_manager
|
|
from vrtManager.instance import wvmInstance
|
|
|
|
from . import livetest
|
|
|
|
P = livetest.PREFIX
|
|
|
|
|
|
class LiveCloneTestCase(SimpleTestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
if not livetest.enabled():
|
|
raise unittest.SkipTest("Set TEST_LIBVIRT_HOST to run the live libvirt tests")
|
|
cls.args = (
|
|
os.environ["TEST_LIBVIRT_HOST"],
|
|
os.environ.get("TEST_LIBVIRT_LOGIN", ""),
|
|
os.environ.get("TEST_LIBVIRT_PASSWORD", ""),
|
|
int(os.environ.get("TEST_LIBVIRT_TYPE", 4)),
|
|
)
|
|
cls.conn = connection_manager.get_connection(*cls.args)
|
|
livetest.cleanup(cls.conn)
|
|
livetest.ensure_pool(cls.conn)
|
|
cls.inventory = livetest.inventory(cls.conn)
|
|
super().setUpClass()
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
try:
|
|
livetest.remove_pool(cls.conn)
|
|
finally:
|
|
super().tearDownClass()
|
|
if livetest.inventory(cls.conn) != cls.inventory:
|
|
raise AssertionError("Live tests changed objects outside the test namespace")
|
|
|
|
def tearDown(self):
|
|
livetest.cleanup(self.conn)
|
|
|
|
def pool_volumes(self):
|
|
pool = self.conn.storagePoolLookupByName(livetest.POOL)
|
|
pool.refresh(0)
|
|
return set(pool.listVolumes())
|
|
|
|
def source(self, name):
|
|
disks = [livetest.create_volume(self.conn, P + f"{name}-{d}") for d in ("a", "b")]
|
|
dom = livetest.define_vm(self.conn, P + name, disks)
|
|
return dom, wvmInstance(*self.args, None, uuid=dom.UUIDString())
|
|
|
|
def clone_data(self, name):
|
|
return {
|
|
"name": P + name,
|
|
"disk-vda": P + name + "-a.qcow2",
|
|
"disk-vdb": P + name + "-b.qcow2",
|
|
"disk_owner_uid": 0,
|
|
"disk_owner_gid": 0,
|
|
}
|
|
|
|
def test_failed_clone_removes_only_its_own_copies(self):
|
|
_, vm = self.source("clone-src")
|
|
taken = livetest.create_volume(self.conn, P + "clone-dst-b") # destination of vdb exists
|
|
before = self.pool_volumes()
|
|
|
|
with self.assertRaises(Exception):
|
|
vm.clone_instance(self.clone_data("clone-dst"))
|
|
|
|
self.assertEqual(self.pool_volumes(), before, "copies left behind or a volume deleted")
|
|
self.assertTrue(livetest.volume_exists(self.conn, taken))
|
|
with self.assertRaises(libvirt.libvirtError):
|
|
self.conn.lookupByName(P + "clone-dst")
|
|
|
|
def test_running_vm_is_not_cloned(self):
|
|
dom, vm = self.source("clone-run")
|
|
dom.create()
|
|
before = self.pool_volumes()
|
|
|
|
with self.assertRaises(Exception):
|
|
vm.clone_instance(self.clone_data("clone-run-copy"))
|
|
|
|
self.assertEqual(self.pool_volumes(), before)
|
|
|
|
def test_clone_of_a_uefi_vm_has_its_own_copy_of_the_nvram(self):
|
|
disk = livetest.create_volume(self.conn, P + "clone-uefi-a")
|
|
dom = livetest.define_vm(self.conn, P + "clone-uefi", [disk], uefi=True)
|
|
dom.createWithFlags(libvirt.VIR_DOMAIN_START_PAUSED) # libvirt makes the NVRAM file at the first start
|
|
dom.destroy()
|
|
vm = wvmInstance(*self.args, None, uuid=dom.UUIDString())
|
|
source = vm.get_nvram()
|
|
|
|
uuid = vm.clone_instance(
|
|
{"name": P + "clone-uefi-copy", "disk-vda": P + "clone-uefi-copy-a.qcow2", "disk_owner_uid": 0, "disk_owner_gid": 0}
|
|
)
|
|
|
|
clone = self.conn.lookupByUUIDString(uuid)
|
|
path = ElementTree.fromstring(clone.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE)).findtext("os/nvram")
|
|
self.assertEqual(path, os.path.join(os.path.dirname(source), P + "clone-uefi-copy_VARS.fd"))
|
|
with vm._nvram_pool() as pool:
|
|
copy = pool.storageVolLookupByName(os.path.basename(path))
|
|
self.assertEqual(copy.info()[1], pool.storageVolLookupByName(os.path.basename(source)).info()[1])
|
|
clone.createWithFlags(libvirt.VIR_DOMAIN_START_PAUSED) # qemu opens the copy
|
|
self.assertEqual(
|
|
ElementTree.fromstring(clone.XMLDesc(0)).findtext("os/nvram"), path, "libvirt replaced the copy"
|
|
)
|
|
clone.destroy()
|
|
|
|
def test_clone_of_a_stopped_vm(self):
|
|
_, vm = self.source("clone-ok")
|
|
uuid = vm.clone_instance(self.clone_data("clone-ok-copy"))
|
|
clone = self.conn.lookupByUUIDString(uuid)
|
|
self.assertEqual(clone.name(), P + "clone-ok-copy")
|
|
self.assertTrue({P + "clone-ok-copy-a.qcow2", P + "clone-ok-copy-b.qcow2"} <= self.pool_volumes())
|