1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-09 03:36:48 +00:00

fix(vrtManager): a request back from other hosts counts on its own host again

A request counts on the host it connected to last. A quota check reads
every host of the user's VMs, and a VM's destruction the other hosts'
files, in the middle of a request that then goes on with the VM's own
host through the objects it kept: it was counted on the last host it
read while it used its own, so a host that does not answer could take
more requests than its limit, and the last host read was charged.

Both checks now give the request back to the host it counted on before.
This commit is contained in:
catborise 2026-11-03 00:10:53 +03:00
parent 491819ed64
commit fb45445492
3 changed files with 33 additions and 1 deletions

View file

@ -12,7 +12,7 @@ from django.utils.translation import gettext_lazy as _
from libvirt import libvirtError
from logs.audit import reason, write
from operations.models import Operation
from vrtManager.connection import wvmConnect
from vrtManager.connection import other_hosts, wvmConnect
from vrtManager.instance import wvmInstance, wvmInstances
from vrtManager.util import OperationError
@ -46,6 +46,7 @@ def get_clone_free_names(size=10):
return free_names
@other_hosts()
def paths_used_on_other_computes(compute, own):
"""The paths in own that the VMs and volumes of the panel's other computes
use (paths_in_use): shared storage holds a file at the same path on every
@ -74,6 +75,7 @@ def disk_gib(disks):
QUOTA_UNVERIFIED = "unverified"
@other_hosts()
def check_user_quota(user, instance, cpu, memory, disk_size):
"""
Which quota the user would exceed by adding these amounts (instances,

View file

@ -135,6 +135,17 @@ def _count_on(connection):
_request.held = connection
@contextlib.contextmanager
def other_hosts():
"""For code that reads other hosts in the middle of a web request, which
then goes on with the host it used before, through the objects it kept:
the request counts on that host again after the block (HOST_REQUESTS)."""
held = getattr(_request, "held", None)
yield
if held is not None:
_count_on(held)
request_started.connect(_request_started, dispatch_uid="vrtManager.connection.request_started")
request_finished.connect(_request_finished, dispatch_uid="vrtManager.connection.request_finished")

View file

@ -295,6 +295,25 @@ class HostRequestsTestCase(unittest.TestCase):
self.end_requests()
self.assertEqual(self.request("h") + self.request("h"), [])
def test_a_request_back_from_other_hosts_counts_on_its_own_again(self):
def run():
request_started.send(sender=None)
self.manager.get_connection("h", "u", "p", CONN_TCP)
with connection.other_hosts():
self.manager.get_connection("g", "u", "p", CONN_TCP)
back.set()
self.done.wait(5)
request_finished.send(sender=None)
back = threading.Event()
thread = threading.Thread(target=run)
thread.start()
self.threads.append(thread)
back.wait(5)
# it holds h again (one of two) and left g
self.assertEqual(self.request("h") + self.request("g") + self.request("g"), [])
self.assertEqual(len(self.request("h")), 1)
def test_threads_outside_a_request_are_not_counted(self):
self.assertEqual(self.request("h") + self.request("h"), [])
self.manager.get_connection("h", "u", "p", CONN_TCP)