From 4b1aaf2a0fa44960e0840daa9673822bfb717da7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Janier=20Rodr=C3=ADguez?= Date: Thu, 30 Jul 2026 14:22:09 +0200 Subject: [PATCH] Recover userservices_limit on IPMachinesService from its server group Since the migration of Physical Machines to server groups as backend, the service stopped reporting its userservices_limit, so it was inherited as UNLIMITED from the base Service class. As a consequence, pools of this service with "Maximum number of services" set to 0 got an unlimited usage info, and the {use}/{usec}/{left}/{total} macros of pools and metapools were replaced by an empty string (metapools) or by 0/0%/-1 (pools). Now the limit is recovered on unmarshal from the servers of the server group, as it was done before the migration. Machines on maintenance are also counted, because the limit is the number of registered machines. --- .../uds/services/PhysicalMachines/service_multi.py | 5 +++++ .../physical_machines/test_service_multi.py | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/server/src/uds/services/PhysicalMachines/service_multi.py b/server/src/uds/services/PhysicalMachines/service_multi.py index f8638d0e6..cf04f2d49 100644 --- a/server/src/uds/services/PhysicalMachines/service_multi.py +++ b/server/src/uds/services/PhysicalMachines/service_multi.py @@ -144,6 +144,11 @@ class IPMachinesService(services.Service): def enumerate_servers(self) -> typing.Iterable['models.Server']: return fields.get_server_group_from_field(self.server_group).servers.filter(maintenance_mode=False) + def userservices_limit_field(self) -> int: + # Machines on maintenance are ALSO counted: the limit is the number of registered + # machines, not the number of currently usable ones (hence not enumerate_servers()). + return fields.get_server_group_from_field(self.server_group).servers.count() + def get_token(self) -> typing.Optional[str]: return self.token.as_str() or None diff --git a/server/tests/services/physical_machines/test_service_multi.py b/server/tests/services/physical_machines/test_service_multi.py index 0a313ac81..8868b0511 100644 --- a/server/tests/services/physical_machines/test_service_multi.py +++ b/server/tests/services/physical_machines/test_service_multi.py @@ -63,6 +63,20 @@ def test_service_data(self) -> None: ) self.assertEqual(service.randomize_host.value, fixtures.SERVICE_MULTI_VALUES_DICT['randomize_host']) + def test_userservices_limit(self) -> None: + service = fixtures.create_service_multi() + # userservices_limit is recovered on unmarshal, so simulate a load from db + service.unmarshal(service.marshal()) + self.assertEqual(service.userservices_limit, len(fixtures.SERVER_GROUP_IPS_MACS)) + + # Machines on maintenance are ALSO counted, the limit is the number of registered machines + server = fields.get_server_group_from_field(service.server_group).servers.all()[0] + server.maintenance_mode = True + server.save(update_fields=['maintenance_mode']) + + service.unmarshal(service.marshal()) + self.assertEqual(service.userservices_limit, len(fixtures.SERVER_GROUP_IPS_MACS)) + def test_service_is_available(self) -> None: """ Test the provider