mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 19:26:48 +00:00
Comments, docstrings and live test names cited item IDs of a roadmap that is not part of the repository. They now say what is meant, or nothing where the sentence stands without them. Test assertions and behavior are unchanged.
112 lines
4.3 KiB
Python
112 lines
4.3 KiB
Python
"""Ownership survives a VM's temporary disappearance or an out-of-band move."""
|
|
|
|
from datetime import timedelta
|
|
from unittest.mock import MagicMock
|
|
|
|
from accounts.models import UserInstance
|
|
from computes.models import Compute
|
|
from computes.utils import refresh_instance_database
|
|
from django.contrib.auth import get_user_model
|
|
from django.test import TestCase, override_settings
|
|
from django.utils import timezone
|
|
from instances.models import Instance, InstanceTombstone
|
|
|
|
UUID = "44444444-4444-4444-4444-444444444444"
|
|
|
|
|
|
class Domain:
|
|
def __init__(self, name, uuid):
|
|
self._name, self._uuid = name, uuid
|
|
|
|
def name(self):
|
|
return self._name
|
|
|
|
def UUIDString(self):
|
|
return self._uuid
|
|
|
|
|
|
class OwnershipTestCase(TestCase):
|
|
def setUp(self):
|
|
self.owner = get_user_model().objects.create_user("owner", password="pw")
|
|
self.host_a = self.compute("host-a")
|
|
self.host_b = self.compute("host-b")
|
|
|
|
def compute(self, name):
|
|
compute = Compute.objects.create(name=name, hostname=f"{name}.example", login="", password="", type=1)
|
|
compute.__dict__["proxy"] = MagicMock()
|
|
self.on(compute, [])
|
|
return compute
|
|
|
|
def on(self, compute, domains):
|
|
compute.proxy.wvm.listAllDomains.return_value = [Domain(n, u) for n, u in domains]
|
|
|
|
def owned_vm(self, compute):
|
|
vm = Instance.objects.create(compute=compute, name="vm", uuid=UUID, is_template=True)
|
|
UserInstance.objects.create(instance=vm, user=self.owner, is_change=True, is_vnc=True)
|
|
return vm
|
|
|
|
def ownership(self, compute):
|
|
vm = Instance.objects.get(compute=compute, uuid=UUID)
|
|
return vm.is_template, [(ui.user, ui.is_change, ui.is_delete, ui.is_vnc) for ui in vm.userinstance_set.all()]
|
|
|
|
def test_vm_that_disappears_and_returns_keeps_its_owners(self):
|
|
self.owned_vm(self.host_a)
|
|
refresh_instance_database(self.host_a) # undefined for a while
|
|
self.assertFalse(Instance.objects.filter(uuid=UUID).exists())
|
|
|
|
self.on(self.host_a, [("vm", UUID)]) # defined again
|
|
refresh_instance_database(self.host_a)
|
|
|
|
self.assertEqual(self.ownership(self.host_a), (True, [(self.owner, True, False, True)]))
|
|
self.assertFalse(InstanceTombstone.objects.exists())
|
|
|
|
def test_move_seen_on_the_new_host_first(self):
|
|
self.owned_vm(self.host_a)
|
|
self.on(self.host_a, [("vm", UUID)])
|
|
self.on(self.host_b, [("vm", UUID)])
|
|
refresh_instance_database(self.host_b) # still listed on A: a copy for now
|
|
self.on(self.host_a, [])
|
|
refresh_instance_database(self.host_a) # gone from A: it moved to B
|
|
|
|
self.assertEqual(self.ownership(self.host_b), (True, [(self.owner, True, False, True)]))
|
|
self.assertFalse(Instance.objects.filter(compute=self.host_a).exists())
|
|
|
|
def test_move_seen_on_the_old_host_first(self):
|
|
self.owned_vm(self.host_a)
|
|
refresh_instance_database(self.host_a)
|
|
self.on(self.host_b, [("vm", UUID)])
|
|
refresh_instance_database(self.host_b)
|
|
|
|
self.assertEqual(self.ownership(self.host_b), (True, [(self.owner, True, False, True)]))
|
|
|
|
def test_copied_uuid_grants_nothing(self):
|
|
self.owned_vm(self.host_a)
|
|
self.on(self.host_a, [("vm", UUID)])
|
|
self.on(self.host_b, [("vm-copy", UUID)])
|
|
refresh_instance_database(self.host_a)
|
|
refresh_instance_database(self.host_b)
|
|
|
|
self.assertEqual(self.ownership(self.host_a), (True, [(self.owner, True, False, True)]))
|
|
self.assertEqual(self.ownership(self.host_b), (False, []))
|
|
|
|
@override_settings(INSTANCE_OWNERSHIP_RETENTION_DAYS=30)
|
|
def test_ownership_is_kept_for_a_bounded_time(self):
|
|
self.owned_vm(self.host_a)
|
|
refresh_instance_database(self.host_a)
|
|
InstanceTombstone.objects.update(removed=timezone.now() - timedelta(days=31))
|
|
|
|
self.on(self.host_a, [("vm", UUID)])
|
|
refresh_instance_database(self.host_a)
|
|
|
|
self.assertEqual(self.ownership(self.host_a), (False, []))
|
|
self.assertFalse(InstanceTombstone.objects.exists())
|
|
|
|
def test_deleted_users_are_skipped(self):
|
|
self.owned_vm(self.host_a)
|
|
refresh_instance_database(self.host_a)
|
|
self.owner.delete()
|
|
|
|
self.on(self.host_a, [("vm", UUID)])
|
|
refresh_instance_database(self.host_a)
|
|
|
|
self.assertEqual(self.ownership(self.host_a), (True, []))
|