Skip to content

Commit 7eabb25

Browse files
fanchen2xhao22
authored andcommitted
KVM: add many_vm_1G case to multi_vms tests
Add many_vm_1G variant that auto-calculates VM count from available host memory. Each VM uses fixed 1024MB. Maximum VM count is limited to 1024. For guest-count calculation, many_vm_1G uses 1024MB guest memory plus 80MB per-guest overhead instead of using raw guest memory size. Set host nofile soft limit inside the case runtime and restore original limits when the case finishes. Extended multi_vms_multi_boot handler with auto_calc_guest_count mode. Signed-off-by: Farrah Chen <farrah.chen@intel.com>
1 parent ba7d3f7 commit 7eabb25

2 files changed

Lines changed: 113 additions & 40 deletions

File tree

KVM/qemu/multi_vms.cfg

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,12 @@
6868
mem_vm2 = 2048
6969
- 4vm:
7070
vms = "vm1 vm2 vm3 vm4"
71+
- many_vm_1G:
72+
type = multi_vms_multi_boot
73+
start_vm = no
74+
host_nofile_limit = 65536
75+
guest_count_mem_overhead = 80
76+
mem = 1024
77+
max_mem = 1024
78+
auto_calc_guest_count = yes
79+
max_guest_count = 1024

KVM/qemu/tests/multi_vms_multi_boot.py

Lines changed: 104 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import logging
77
import random
8+
import resource
89

910
from virttest import env_process
1011
from virttest import error_context
@@ -14,13 +15,58 @@
1415
LOG = logging.getLogger("avocado.test")
1516

1617

18+
def _set_host_nofile_limit(test, params):
19+
"""Set host nofile soft limit for a large number of guest cases and return original limits."""
20+
target_nofile = int(params.get_numeric("host_nofile_limit", 65536))
21+
original_limits = resource.getrlimit(resource.RLIMIT_NOFILE)
22+
soft_limit, hard_limit = original_limits
23+
24+
if hard_limit == resource.RLIM_INFINITY:
25+
new_soft_limit = target_nofile
26+
else:
27+
new_soft_limit = min(target_nofile, hard_limit)
28+
29+
if soft_limit >= new_soft_limit:
30+
return original_limits
31+
32+
resource.setrlimit(resource.RLIMIT_NOFILE, (new_soft_limit, hard_limit))
33+
if new_soft_limit < target_nofile:
34+
test.log.warning(
35+
"host nofile hard limit is %s, case soft limit set to %s instead of %s",
36+
hard_limit,
37+
new_soft_limit,
38+
target_nofile,
39+
)
40+
else:
41+
test.log.info("host nofile soft limit set to %s for this case", new_soft_limit)
42+
43+
return original_limits
44+
45+
46+
def _prepare_auto_calc_guest_count(params):
47+
"""Generate vm list for auto_calc_guest_count mode."""
48+
guest_mem = int(params.get_numeric("mem", params.get_numeric("start_mem", 1024)))
49+
guest_count_mem = guest_mem + int(
50+
params.get_numeric("guest_count_mem_overhead", 0)
51+
)
52+
host_usable_mem = int(utils_misc.get_usable_memory_size())
53+
guest_num = host_usable_mem // guest_count_mem
54+
max_guest_count = params.get("max_guest_count")
55+
if max_guest_count:
56+
guest_num = min(guest_num, int(max_guest_count))
57+
vm_names = ["vm%s" % idx for idx in range(1, guest_num + 1)]
58+
params["vms"] = " ".join(vm_names)
59+
return guest_count_mem, host_usable_mem, vm_names
60+
61+
1762
def _calc_default_mem_series(params, vm_names):
1863
"""
1964
Calculate a default memory series based on the generator type.
2065
2166
Supported generators:
2267
- linear: increments by mem_step from start_mem to memory_limit
2368
- random_32g_window: random samples within sliding 32G windows
69+
Note: auto_calc_guest_count preparation is handled outside this function.
2470
"""
2571
# Supported: "linear" (default fallback) or "random_32g_window" (used by current cfg)
2672
mem_generator = params.get("mem_generator", "linear")
@@ -136,43 +182,61 @@ def run(test, params, env):
136182

137183
timeout = int(params.get_numeric("login_timeout", 240))
138184

139-
vm_names = params.objects("vms")
140-
if not vm_names:
141-
test.cancel("No VMs configured for multi_vms_multi_boot")
142-
143-
iteration_plan = _resolve_iteration_plan(params, vm_names)
144-
145-
if not iteration_plan:
146-
test.cancel("No valid iterations resolved for multi_vms_multi_boot")
147-
148-
test.log.info("Total iterations: %s, VMs per iteration: %s",
149-
len(iteration_plan), len(vm_names))
150-
151-
for iteration, vm_param_overrides in enumerate(iteration_plan, start=1):
152-
started_vms = []
153-
try:
154-
override_desc = ", ".join(
155-
"%s(mem=%s)" % (vm_name, vm_param_overrides.get(vm_name, {}).get("mem", "default"))
156-
for vm_name in vm_names
157-
)
158-
error_context.context(
159-
"Iteration %s/%s: %s"
160-
% (iteration, len(iteration_plan), override_desc),
161-
test.log.info,
162-
)
163-
164-
for vm_name in vm_names:
165-
vm_params = params.object_params(vm_name)
166-
vm_params["start_vm"] = "yes"
167-
for key, value in vm_param_overrides.get(vm_name, {}).items():
168-
vm_params[key] = value
169-
env_process.preprocess_vm(test, vm_params, env, vm_name)
170-
started_vms.append(env.get_vm(vm_name))
171-
172-
for vm in started_vms:
173-
vm.verify_alive()
174-
session = vm.wait_for_login(timeout=timeout)
175-
session.close()
176-
finally:
177-
for vm in started_vms:
178-
vm.destroy(gracefully=False)
185+
auto_calc_guest_count = params.get("auto_calc_guest_count", "no") == "yes"
186+
original_nofile_limits = None
187+
try:
188+
if auto_calc_guest_count:
189+
original_nofile_limits = _set_host_nofile_limit(test, params)
190+
191+
vm_names = params.objects("vms")
192+
# If auto_calc_guest_count is disabled, vms must be explicitly configured
193+
if not vm_names and not auto_calc_guest_count:
194+
test.cancel("No VMs configured for multi_vms_multi_boot")
195+
# Validate auto_calc_guest_count requirements
196+
if auto_calc_guest_count:
197+
guest_count_mem, host_usable_mem, vm_names = _prepare_auto_calc_guest_count(params)
198+
if host_usable_mem < guest_count_mem:
199+
test.fail(
200+
"Not enough usable host memory for auto_calc_guest_count. "
201+
"required=%dM usable=%dM" % (guest_count_mem, host_usable_mem)
202+
)
203+
204+
iteration_plan = _resolve_iteration_plan(params, vm_names)
205+
206+
if not iteration_plan:
207+
test.cancel("No valid iterations resolved for multi_vms_multi_boot")
208+
209+
test.log.info("Total iterations: %s, VMs per iteration: %s",
210+
len(iteration_plan), len(vm_names))
211+
212+
for iteration, vm_param_overrides in enumerate(iteration_plan, start=1):
213+
started_vms = []
214+
try:
215+
override_desc = ", ".join(
216+
"%s(mem=%s)" % (vm_name, vm_param_overrides.get(vm_name, {}).get("mem", "default"))
217+
for vm_name in vm_names
218+
)
219+
error_context.context(
220+
"Iteration %s/%s: %s"
221+
% (iteration, len(iteration_plan), override_desc),
222+
test.log.info,
223+
)
224+
225+
for vm_name in vm_names:
226+
vm_params = params.object_params(vm_name)
227+
vm_params["start_vm"] = "yes"
228+
for key, value in vm_param_overrides.get(vm_name, {}).items():
229+
vm_params[key] = value
230+
env_process.preprocess_vm(test, vm_params, env, vm_name)
231+
started_vms.append(env.get_vm(vm_name))
232+
233+
for vm in started_vms:
234+
vm.verify_alive()
235+
session = vm.wait_for_login(timeout=timeout)
236+
session.close()
237+
finally:
238+
for vm in started_vms:
239+
vm.destroy(gracefully=False)
240+
finally:
241+
if original_nofile_limits is not None:
242+
resource.setrlimit(resource.RLIMIT_NOFILE, original_nofile_limits)

0 commit comments

Comments
 (0)