diff --git a/instances/utils.py b/instances/utils.py index 31800dd4..9b9b3b48 100644 --- a/instances/utils.py +++ b/instances/utils.py @@ -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, diff --git a/vrtManager/connection.py b/vrtManager/connection.py index a00392df..949c4f19 100644 --- a/vrtManager/connection.py +++ b/vrtManager/connection.py @@ -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") diff --git a/vrtManager/tests/test_connection.py b/vrtManager/tests/test_connection.py index 54940e49..27f32693 100644 --- a/vrtManager/tests/test_connection.py +++ b/vrtManager/tests/test_connection.py @@ -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)