[PATCH] [kvm-autotest] tests.cgroup: Add TestFreezer

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This subtest tests the 'freezer.state' cgroup functionality. It assignes the
virtual machine into freezer cgroup, schedule cpu-intensive work and verifies
the correct function in both states (frozen/thawed) during long and short
period of time.

 * Adds TestFreezer (freezer) test
 * Adds assign_vm_into_cgroup() function
 * Code cleanup

Signed-off-by: Lukas Doktor <ldoktor@xxxxxxxxxx>
---
 client/tests/cgroup/cgroup_common.py |   16 +---
 client/tests/kvm/tests/cgroup.py     |  159 +++++++++++++++++++++++++++++++---
 2 files changed, 146 insertions(+), 29 deletions(-)

diff --git a/client/tests/cgroup/cgroup_common.py b/client/tests/cgroup/cgroup_common.py
index 0c86398..7d5daf2 100755
--- a/client/tests/cgroup/cgroup_common.py
+++ b/client/tests/cgroup/cgroup_common.py
@@ -6,25 +6,11 @@ Helpers for cgroup testing.
 @copyright: 2011 Red Hat Inc.
 @author: Lukas Doktor <ldoktor@xxxxxxxxxx>
 """
-import logging, os, shutil, subprocess, time, traceback
+import logging, os, shutil, subprocess, time
 from tempfile import mkdtemp
 from autotest_lib.client.bin import utils
 from autotest_lib.client.common_lib import error
 
-def _traceback(name, exc_info):
-    """
-    Formats traceback into lines "name: line\nname: line"
-    @param name: desired line preposition
-    @param exc_info: sys.exc_info of the exception
-    @return: string which contains beautifully formatted exception
-    """
-    out = "\n"
-    for line in traceback.format_exception(exc_info[0], exc_info[1],
-                                           exc_info[2]):
-        out += "%s: %s" % (name, line)
-    return out
-
-
 class Cgroup(object):
     """
     Cgroup handling class.
diff --git a/client/tests/kvm/tests/cgroup.py b/client/tests/kvm/tests/cgroup.py
index f31ef0c..b482bce 100644
--- a/client/tests/kvm/tests/cgroup.py
+++ b/client/tests/kvm/tests/cgroup.py
@@ -40,6 +40,20 @@ def run_cgroup(test, params, env):
             raise error.TestFail("WM [%s] had to be recreated" % err[:-2])
 
 
+    def assign_vm_into_cgroup(vm, cgroup, pwd=None):
+        """
+        Assigns all threads of VM into cgroup
+        @param vm: desired VM
+        @param cgroup: cgroup handler
+        @param pwd: desired cgroup's pwd, cgroup index or None for root cgroup
+        """
+        if isinstance(pwd, int):
+            pwd = cgroup.cgroups[pwd]
+        cgroup.set_cgroup(vm.get_shell_pid(),pwd)
+        for pid in utils.get_children_pids(vm.get_shell_pid()):
+            cgroup.set_cgroup(int(pid), pwd)
+
+
     def distance(actual, reference):
         """
         Absolute value of relative distance of two numbers
@@ -118,10 +132,12 @@ def run_cgroup(test, params, env):
             utils.system("dd if=/dev/zero of=%s bs=1M count=8 &>/dev/null"
                          % (host_file.name))
             ret_file = host_file
-            logging.debug("add_file_drive: new file %s as drive", host_file.name)
+            logging.debug("add_file_drive: new file %s as drive",
+                          host_file.name)
         else:
             ret_file = None
-            logging.debug("add_file_drive: using file %s as drive", host_file.name)
+            logging.debug("add_file_drive: using file %s as drive",
+                          host_file.name)
 
         out = vm.monitor.cmd("pci_add auto storage file=%s,if=%s,snapshot=off,"
                              "cache=off" % (host_file.name, driver))
@@ -277,10 +293,7 @@ def run_cgroup(test, params, env):
             blkio.initialize(self.modules)
             for i in range(2):
                 pwd.append(blkio.mk_cgroup())
-                blkio.set_cgroup(self.vms[i].get_shell_pid(), pwd[i])
-                # Move all existing threads into cgroup
-                for tmp in utils.get_children_pids(self.vms[i].get_shell_pid()):
-                    blkio.set_cgroup(int(tmp), pwd[i])
+                assign_vm_into_cgroup(self.vms[i], blkio, pwd[i])
             self.blkio.set_property("blkio.weight", 100, pwd[0])
             self.blkio.set_property("blkio.weight", 1000, pwd[1])
 
@@ -475,9 +488,7 @@ def run_cgroup(test, params, env):
             for i in range(len(self.cgroups)):
                 logging.info("Limiting speed to: %s", (self.speeds[i]))
                 # Assign all threads of vm
-                self.cgroup.set_cgroup(self.vm.get_shell_pid(), self.cgroups[i])
-                for pid in utils.get_children_pids(self.vm.get_shell_pid()):
-                    self.cgroup.set_cgroup(int(pid), self.cgroups[i])
+                assign_vm_into_cgroup(self.vm, self.cgroup, self.cgroups[i])
 
                 # Standard test-time is 60s. If the slice time is less than 30s,
                 # test-time is prolonged to 30s per slice.
@@ -668,10 +679,7 @@ def run_cgroup(test, params, env):
 
             self.cgroup.initialize(self.modules)
             self.cgroup.mk_cgroup()
-            self.cgroup.set_cgroup(self.vm.get_shell_pid(),
-                                   self.cgroup.cgroups[0])
-            for pid in utils.get_children_pids(self.vm.get_shell_pid()):
-                self.cgroup.set_cgroup(int(pid), self.cgroup.cgroups[0])
+            assign_vm_into_cgroup(self.vm, self.cgroup, 0)
 
             # Test dictionary
             # Beware of persistence of some setting to another round!!!
@@ -765,6 +773,128 @@ def run_cgroup(test, params, env):
 
             return ("All restrictions enforced successfully.")
 
+
+    class TestFreezer:
+        """
+        Tests the freezer.state cgroup functionality. (it freezes the guest
+        and unfreeze it again)
+        """
+        def __init__(self, vms, modules):
+            """
+            Initialization
+            @param vms: list of vms
+            @param modules: initialized cgroup module class
+            """
+            self.vm = vms[0]      # Virt machines
+            self.modules = modules          # cgroup module handler
+            self.cgroup = Cgroup('freezer', '')   # cgroup blkio handler
+            self.files = None   # Temporary files (files of virt disks)
+            self.devices = None # Temporary virt devices
+
+
+        def cleanup(self):
+            err = ""
+            try:
+                self.cgroup.set_property('freezer.state', 'THAWED',
+                                         self.cgroup.cgroups[0])
+            except Exception, failure_detail:
+                err += "\nCan't unfreeze vm: %s" % failure_detail
+
+            try:
+                _ = self.vm.wait_for_login(timeout=30)
+                _.cmd('rm -f /tmp/freeze-lock')
+                _.close()
+            except Exception, failure_detail:
+                err += "\nCan't stop the stresses."
+
+            try:
+                del(self.cgroup)
+            except Exception, failure_detail:
+                err += "\nCan't remove Cgroup: %s" % failure_detail
+
+            if err:
+                logging.error("Some cleanup operations failed: %s", err)
+                raise error.TestFail("Some cleanup operations failed: %s" %
+                                      err)
+
+
+        def init(self):
+            """
+            Initialization
+             * prepares one cgroup and assign vm to it
+            """
+            self.cgroup.initialize(self.modules)
+            self.cgroup.mk_cgroup()
+            assign_vm_into_cgroup(self.vm, self.cgroup, 0)
+
+
+        def run(self):
+            """
+            Actual test:
+             * Freezes the guest and thaws it again couple of times
+             * verifies that guest is frozen and runs when expected
+            """
+            def get_stat(pid):
+                """
+                Gather statistics of pid+1st level subprocesses cpu usage
+                @param pid: PID of the desired process
+                @return: sum of all cpu-related values of 1st level subprocesses
+                """
+                out = None
+                for i in range(10):
+                    try:
+                        out = utils.system_output("cat /proc/%s/task/*/stat" %
+                                                   pid)
+                    except error.CmdError:
+                        out = None
+                    else:
+                        break
+                out = out.split('\n')
+                ret = 0
+                for i in out:
+                    ret += sum([int(_) for _ in i.split(' ')[13:17]])
+                return ret
+
+
+            session = self.vm.wait_for_serial_login(timeout=30)
+            session.cmd('touch /tmp/freeze-lock')
+            session.sendline('while [ -e /tmp/freeze-lock ]; do :; done')
+            cgroup = self.cgroup
+            pid = self.vm.get_pid()
+
+            for tsttime in [0.5,3,20]:
+                # Let it work for short, mid and long period of time
+                logging.info("FREEZING (%ss)", tsttime)
+                # Death line for freezing is 1s
+                cgroup.set_property('freezer.state', 'FROZEN',
+                                    cgroup.cgroups[0], check=False)
+                time.sleep(1)
+                _ = cgroup.get_property('freezer.state', cgroup.cgroups[0])
+                if 'FROZEN' not in _:
+                    raise error.TestFail("Couldn't freeze the VM: state %s" % _)
+                stat_ = get_stat(pid)
+                time.sleep(tsttime)
+                stat = get_stat(pid)
+                if stat != stat_:
+                    raise error.TestFail('Process was running in FROZEN state; '
+                                         'iteration %s, stat=%s, stat_=%s, '
+                                         'diff=%s' %
+                                          (i, stat, stat_, stat-stat_))
+                logging.info("THAWING (%ss)", tsttime)
+                self.cgroup.set_property('freezer.state', 'THAWED',
+                                         self.cgroup.cgroups[0])
+                stat_ = get_stat(pid)
+                time.sleep(tsttime)
+                stat = get_stat(pid)
+                if (stat - stat_) < (90*tsttime):
+                    raise error.TestFail('Process was not active in FROZEN'
+                                         'state; iteration %s, stat=%s, '
+                                         'stat_=%s, diff=%s' %
+                                          (i, stat, stat_, stat-stat_))
+
+            return ("Freezer works fine")
+
+
     # Setup
     # TODO: Add all new tests here
     tests = {"blkio_bandwidth_weigth_read"  : TestBlkioBandwidthWeigthRead,
@@ -774,9 +904,10 @@ def run_cgroup(test, params, env):
              "blkio_throttle_multiple_read" : TestBlkioThrottleMultipleRead,
              "blkio_throttle_multiple_write" : TestBlkioThrottleMultipleWrite,
              "devices_access"               : TestDevicesAccess,
+             "freezer"                      : TestFreezer,
             }
     modules = CgroupModules()
-    if (modules.init(['blkio', 'devices']) <= 0):
+    if (modules.init(['blkio', 'devices', 'freezer']) <= 0):
         raise error.TestFail('Can\'t mount any cgroup modules')
     # Add all vms
     vms = []
-- 
1.7.6.4

--
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


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux