mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-11 12:46:49 +00:00
test: test files named by their topic, one file per topic
- console settings were split over four files; who sees the form, the listen address, and the settings themselves are test_console_settings, and who may open a console is test_console_access; - the three template files are test_templates; - the quota lock test joins test_quota; - accounts' test_security_fixes held two topics: the SSH key tests are test_ssh_keys, the owner-row delete redirect is in test_views; - instances' test_security_mutations, who may change a VM, is test_permissions. The suite runs the same 2097 tests.
This commit is contained in:
parent
bdc8a6755c
commit
f3003bb414
15 changed files with 541 additions and 606 deletions
|
|
@ -18,6 +18,10 @@ from libvirt import VIR_DOMAIN_PAUSED, VIR_DOMAIN_RUNNING
|
|||
from operations.models import Operation
|
||||
from vrtManager.util import OperationError
|
||||
import socket
|
||||
import threading
|
||||
import time
|
||||
from django.db import connection
|
||||
from django.test import Client, TransactionTestCase, override_settings
|
||||
|
||||
|
||||
def vm_reader(vcpu=2, memory=1024, disk_gib=10, pending=None):
|
||||
|
|
@ -292,3 +296,58 @@ class QuotaWithDownHostTestCase(TestCase):
|
|||
get_settings() # app settings are normally loaded by middleware
|
||||
|
||||
self.assertEqual(check_user_quota(user, 1, 1, 128, 1), QUOTA_UNVERIFIED)
|
||||
|
||||
|
||||
QUOTA_CPUS = 4
|
||||
|
||||
|
||||
# Sessions and messages in cookies: concurrent writes to the in-memory test
|
||||
# database would fail for reasons unrelated to the quota race.
|
||||
@override_settings(
|
||||
SESSION_ENGINE="django.contrib.sessions.backends.signed_cookies",
|
||||
MESSAGE_STORAGE="django.contrib.messages.storage.cookie.CookieStorage",
|
||||
)
|
||||
|
||||
|
||||
class QuotaRaceTestCase(TransactionTestCase):
|
||||
"""Two concurrent resizes of one user's VMs must not both pass the quota."""
|
||||
|
||||
def setUp(self):
|
||||
self.user = get_user_model().objects.create_user("quota_user", password="pw")
|
||||
compute = Compute.objects.create(name="quota-compute", hostname="127.0.0.1", login="", password="", type=4)
|
||||
self.vms = [
|
||||
Instance.objects.create(compute=compute, name=f"quota-vm-{i}", uuid=f"1111111{i}-2222-3333-4444-555555555555")
|
||||
for i in range(2)
|
||||
]
|
||||
for vm in self.vms:
|
||||
UserInstance.objects.create(user=self.user, instance=vm, is_change=True)
|
||||
self.allocated = 2 # two VMs with one vCPU each
|
||||
|
||||
def fake_quota(self, user, instance, cpu, memory, disk):
|
||||
seen = self.allocated
|
||||
time.sleep(0.3) # widen the window between the check and the change
|
||||
return "cpu" if seen + cpu > QUOTA_CPUS else ""
|
||||
|
||||
def fake_resize(self, cur_vcpu, vcpu):
|
||||
self.allocated += int(vcpu) - 1
|
||||
|
||||
def resize(self, vm):
|
||||
client = Client()
|
||||
client.force_login(self.user)
|
||||
client.post(reverse("instances:resizevm_cpu", args=[vm.id]), {"vcpu": 3, "cur_vcpu": 3})
|
||||
connection.close()
|
||||
|
||||
def test_second_concurrent_resize_is_refused(self):
|
||||
with patch("instances.views.utils.check_user_quota", self.fake_quota), patch(
|
||||
"instances.models.wvmInstance"
|
||||
) as wvm:
|
||||
wvm.return_value.get_vcpu.return_value = 1
|
||||
wvm.return_value.instance.isActive.return_value = False # vCPUs change on a shut-off VM
|
||||
wvm.return_value.resize_cpu.side_effect = self.fake_resize
|
||||
threads = [threading.Thread(target=self.resize, args=(vm,)) for vm in self.vms]
|
||||
for t in threads:
|
||||
t.start()
|
||||
for t in threads:
|
||||
t.join()
|
||||
self.assertEqual(wvm.return_value.resize_cpu.call_count, 1)
|
||||
self.assertLessEqual(self.allocated, QUOTA_CPUS)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue