| """ |
| Library to perform pre/post test setup for KVM autotest. |
| """ |
| import os, logging |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.bin import utils |
| |
| |
| class HugePageConfig(object): |
| def __init__(self, params): |
| """ |
| Gets environment variable values and calculates the target number |
| of huge memory pages. |
| |
| @param params: Dict like object containing parameters for the test. |
| """ |
| self.vms = len(params.objects("vms")) |
| self.mem = int(params.get("mem")) |
| self.max_vms = int(params.get("max_vms", 0)) |
| self.hugepage_path = '/mnt/kvm_hugepage' |
| self.hugepage_size = self.get_hugepage_size() |
| self.target_hugepages = self.get_target_hugepages() |
| self.kernel_hp_file = '/proc/sys/vm/nr_hugepages' |
| |
| |
| def get_hugepage_size(self): |
| """ |
| Get the current system setting for huge memory page size. |
| """ |
| meminfo = open('/proc/meminfo', 'r').readlines() |
| huge_line_list = [h for h in meminfo if h.startswith("Hugepagesize")] |
| try: |
| return int(huge_line_list[0].split()[1]) |
| except ValueError, e: |
| raise ValueError("Could not get huge page size setting from " |
| "/proc/meminfo: %s" % e) |
| |
| |
| def get_target_hugepages(self): |
| """ |
| Calculate the target number of hugepages for testing purposes. |
| """ |
| if self.vms < self.max_vms: |
| self.vms = self.max_vms |
| # memory of all VMs plus qemu overhead of 64MB per guest |
| vmsm = (self.vms * self.mem) + (self.vms * 64) |
| return int(vmsm * 1024 / self.hugepage_size) |
| |
| |
| @error.context_aware |
| def set_hugepages(self): |
| """ |
| Sets the hugepage limit to the target hugepage value calculated. |
| """ |
| error.context("setting hugepages limit to %s" % self.target_hugepages) |
| hugepage_cfg = open(self.kernel_hp_file, "r+") |
| hp = hugepage_cfg.readline() |
| while int(hp) < self.target_hugepages: |
| loop_hp = hp |
| hugepage_cfg.write(str(self.target_hugepages)) |
| hugepage_cfg.flush() |
| hugepage_cfg.seek(0) |
| hp = int(hugepage_cfg.readline()) |
| if loop_hp == hp: |
| raise ValueError("Cannot set the kernel hugepage setting " |
| "to the target value of %d hugepages." % |
| self.target_hugepages) |
| hugepage_cfg.close() |
| logging.debug("Successfuly set %s large memory pages on host ", |
| self.target_hugepages) |
| |
| |
| @error.context_aware |
| def mount_hugepage_fs(self): |
| """ |
| Verify if there's a hugetlbfs mount set. If there's none, will set up |
| a hugetlbfs mount using the class attribute that defines the mount |
| point. |
| """ |
| error.context("mounting hugepages path") |
| if not os.path.ismount(self.hugepage_path): |
| if not os.path.isdir(self.hugepage_path): |
| os.makedirs(self.hugepage_path) |
| cmd = "mount -t hugetlbfs none %s" % self.hugepage_path |
| utils.system(cmd) |
| |
| |
| def setup(self): |
| logging.debug("Number of VMs this test will use: %d", self.vms) |
| logging.debug("Amount of memory used by each vm: %s", self.mem) |
| logging.debug("System setting for large memory page size: %s", |
| self.hugepage_size) |
| logging.debug("Number of large memory pages needed for this test: %s", |
| self.target_hugepages) |
| self.set_hugepages() |
| self.mount_hugepage_fs() |
| |
| |
| @error.context_aware |
| def cleanup(self): |
| error.context("trying to dealocate hugepage memory") |
| try: |
| utils.system("umount %s" % self.hugepage_path) |
| except error.CmdError: |
| return |
| utils.system("echo 0 > %s" % self.kernel_hp_file) |
| logging.debug("Hugepage memory successfuly dealocated") |