From: pradeep <psuriset@xxxxxxxxxxxxxxxxxx> This test verifies memory ballooning functionality for KVM guests. It will boot a guest with -balloon virtio, increase and decrease memory on qemu monitor, verifying the changes, for a given number of iterations. Changes from v3: * Also check current memory reported by the guest to see if ballooning was successful * Added a new method to vm, get_current_memory_size(), to report total memory for the guest OS at a given time * Refactored some test functions * Resets ballooned memory at the end of the test (which exercises a little more the functionality and avoids problems when running through multiple iterations). * Make the test run for at least 5 iterations, configurable in the 'iterations' parameter. This way the functionality is more thoroughly tested, giving testers with particular needs some run to customize how many iterations they want Signed-off-by: Pradeep Kumar Surisetty <psuriset@xxxxxxxxxxxxxxxxxx> Signed-off-by: Lucas Meneghel Rodrigues <lmr@xxxxxxxxxx> --- client/tests/kvm/kvm_vm.py | 18 +++++- client/tests/kvm/tests/balloon_check.py | 102 +++++++++++++++++++++++++++++++ client/tests/kvm/tests_base.cfg.sample | 9 +++- 3 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 client/tests/kvm/tests/balloon_check.py diff --git a/client/tests/kvm/kvm_vm.py b/client/tests/kvm/kvm_vm.py index 047505a..3c643fd 100755 --- a/client/tests/kvm/kvm_vm.py +++ b/client/tests/kvm/kvm_vm.py @@ -916,15 +916,19 @@ class VM: session.close() - def get_memory_size(self): + def get_memory_size(self, cmd=None): """ - Get memory size of the VM. + Get bootup memory size of the VM. + + @param check_cmd: Command used to check memory. If not provided, + self.params.get("mem_chk_cmd") will be used. """ session = self.remote_login() if not session: return None try: - cmd = self.params.get("mem_chk_cmd") + if not cmd: + cmd = self.params.get("mem_chk_cmd") s, mem_str = session.get_command_status_output(cmd) if s != 0: return None @@ -941,3 +945,11 @@ class VM: return int(mem_size) finally: session.close() + + + def get_current_memory_size(self): + """ + Get current memory size of the VM, rather than bootup memory. + """ + cmd = self.params.get("mem_chk_cur_cmd") + return self.get_memory_size(cmd) diff --git a/client/tests/kvm/tests/balloon_check.py b/client/tests/kvm/tests/balloon_check.py new file mode 100644 index 0000000..2496785 --- /dev/null +++ b/client/tests/kvm/tests/balloon_check.py @@ -0,0 +1,102 @@ +import re, string, logging, random, time +from autotest_lib.client.common_lib import error +import kvm_test_utils, kvm_utils + +def run_balloon_check(test, params, env): + """ + Check Memory ballooning: + 1) Boot a guest + 2) Change the memory between 60% to 95% of memory of guest using ballooning + 3) check memory info + + @param test: kvm test object + @param params: Dictionary with the test parameters + @param env: Dictionary with test environment. + """ + def check_ballooned_memory(): + """ + Verify the actual memory reported by monitor command info balloon. If + the operation failed, increase the failure counter. + + @return: Number of failures occurred during operation. + """ + fail = 0 + status, output = vm.send_monitor_cmd("info balloon") + if status != 0: + logging.error("qemu monitor command failed: info balloon") + fail += 1 + return 0 + return int(re.findall("\d+", output)[0]), fail + + + def balloon_memory(new_mem): + """ + Baloon memory to new_mem and verifies on both qemu monitor and + guest OS if change worked. + + @param new_mem: New desired memory. + @return: Number of failures occurred during operation. + """ + fail = 0 + logging.info("Changing VM memory to %s", new_mem) + vm.send_monitor_cmd("balloon %s" % new_mem) + time.sleep(20) + + ballooned_mem, cfail = check_ballooned_memory() + fail += cfail + # Verify whether the VM machine reports the correct new memory + if ballooned_mem != new_mem: + logging.error("Memory ballooning failed while changing memory " + "from %s to %s", actual_mem, new_mem) + fail += 1 + + # Verify whether the guest OS reports the correct new memory + current_mem_guest = vm.get_current_memory_size() + + # Current memory figures will allways be a little smaller than new + # memory. If they are higher, ballooning failed on guest perspective + if current_mem_guest > new_mem: + logging.error("Guest OS reports %s of RAM, but new ballooned RAM " + "is %s", current_mem_guest, new_mem) + fail += 1 + return fail + + + fail = 0 + vm = kvm_test_utils.get_living_vm(env, params.get("main_vm")) + session = kvm_test_utils.wait_for_login(vm) + + # Upper limit that we can raise the memory + vm_assigned_mem = int(params.get("mem")) + + # Check memory size + logging.info("Memory check") + boot_mem = vm.get_memory_size() + if boot_mem != vm_assigned_mem: + logging.error("Memory size mismatch:") + logging.error(" Assigned to VM: %s" % expected_mem) + logging.error(" Reported by guest OS at boot: %s" % actual_mem) + fail += 1 + + # Check if info balloon works or not + current_vm_mem, cfail = check_ballooned_memory() + if cfail: + fail += cfail + if current_vm_mem: + logging.info("Current VM memory according to ballooner: %s", + current_vm_mem) + + # Reduce memory to random size between 60% to 95% of max memory size + percent = random.uniform(0.6, 0.95) + new_mem = int(percent * vm_assigned_mem) + fail += balloon_memory(new_mem) + + # Reset memory value to original memory assigned on qemu. This will ensure + # we won't trigger guest OOM killer while running multiple iterations + fail += balloon_memory(vm_assigned_mem) + + # Close stablished session + session.close() + # Check if any failures happen during the whole test + if fail != 0: + raise error.TestFail("Memory ballooning test failed") diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample index 4baa1dc..e77201b 100644 --- a/client/tests/kvm/tests_base.cfg.sample +++ b/client/tests/kvm/tests_base.cfg.sample @@ -171,6 +171,11 @@ variants: drift_threshold = 10 drift_threshold_single = 3 + - balloon_check: install setup unattended_install + type = balloon_check + extra_params += "-balloon virtio" + iterations = 5 + - stress_boot: install setup unattended_install type = stress_boot max_vms = 5 @@ -381,6 +386,7 @@ variants: file_transfer_client = scp file_transfer_port = 22 mem_chk_cmd = dmidecode -t 17 | awk -F: '/Size/ {print $2}' + mem_chk_cur_cmd = grep MemTotal /proc/meminfo cpu_chk_cmd = grep -c processor /proc/cpuinfo timedrift: extra_params += " -no-kvm-pit-reinjection" @@ -777,6 +783,7 @@ variants: cpu_chk_cmd = echo %NUMBER_OF_PROCESSORS% mem_chk_cmd = wmic memphysical + mem_chk_cur_cmd = wmic memphysical unattended_install: timeout = 7200 @@ -1179,7 +1186,7 @@ variants: image_boot=yes -virtio|virtio_blk|e1000: +virtio|virtio_blk|e1000|balloon_check: only Fedora.11 Fedora.12 Win2008 WinVista Win7 openSUSE-11 Ubuntu-8.10-server -- 1.6.6.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html