All of lore.kernel.org
 help / color / mirror / Atom feed
* [autotest][PATCH] cgroup test + modifications
@ 2011-08-15 12:23 Lukas Doktor
  2011-08-15 12:23 ` [PATCH 1/4] [NEW] cgroup test * general smoke_test + module dependend subtests (memory test included) * library for future use in other tests (kvm) Lukas Doktor
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Lukas Doktor @ 2011-08-15 12:23 UTC (permalink / raw)
  To: autotest, kvm, kvm-autotest, fyang, lmr, ldoktor, jzupka


Hi,

I changed a bit the structure and added the cpuset test.

The first patch is equal to previous post (including the missing file). Other pa
tches are bugfixies and new cpuset test.

Please let me know if this structure is usable so I can continue in test develop
ment.

Regards,
Lukáš
_______________________________________________
Autotest mailing list
Autotest@test.kernel.org
http://test.kernel.org/cgi-bin/mailman/listinfo/autotest

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/4] [NEW] cgroup test * general smoke_test + module dependend subtests (memory test included) * library for future use in other tests (kvm)
  2011-08-15 12:23 [autotest][PATCH] cgroup test + modifications Lukas Doktor
@ 2011-08-15 12:23 ` Lukas Doktor
  2011-08-18 11:33   ` Jiri Zupka
  2011-08-15 12:23 ` [PATCH 2/4] bugfixies Lukas Doktor
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Lukas Doktor @ 2011-08-15 12:23 UTC (permalink / raw)
  To: autotest, kvm, kvm-autotest, fyang, lmr, ldoktor, jzupka; +Cc: root

From: root <root@dhcp-26-193.brq.redhat.com>

cgroup.py:
* structure for different cgroup subtests
* contains basic "cgroup-memory" test

cgroup_common.py:
* library for cgroup handling (intended to be used from kvm test in the future)
* universal smoke_test for every module

cgroup_client.py:
* application which is executed and controled using cgroups
* contains smoke, memory, cpu and devices tests which were manually tested to break cgroup rules and will be used in the cgroup.py subtests

Signed-off-by: Lukas Doktor <ldoktor@redhat.com>
---
 client/tests/cgroup/cgroup.py        |  239 +++++++++++++++++++++++++
 client/tests/cgroup/cgroup_client.py |  116 ++++++++++++
 client/tests/cgroup/cgroup_common.py |  327 ++++++++++++++++++++++++++++++++++
 client/tests/cgroup/control          |   12 ++
 4 files changed, 694 insertions(+), 0 deletions(-)
 create mode 100755 client/tests/cgroup/cgroup.py
 create mode 100755 client/tests/cgroup/cgroup_client.py
 create mode 100755 client/tests/cgroup/cgroup_common.py
 create mode 100644 client/tests/cgroup/control

diff --git a/client/tests/cgroup/cgroup.py b/client/tests/cgroup/cgroup.py
new file mode 100755
index 0000000..112f012
--- /dev/null
+++ b/client/tests/cgroup/cgroup.py
@@ -0,0 +1,239 @@
+from autotest_lib.client.bin import test
+from autotest_lib.client.common_lib import error
+import os, logging
+import time
+from cgroup_common import Cgroup as CG
+from cgroup_common import CgroupModules
+
+class cgroup(test.test):
+    """
+    Tests the cgroup functionalities
+    """
+    version = 1
+    _client = ""
+    modules = CgroupModules()
+
+
+    def run_once(self):
+        """
+	    Try to access different resources which are restricted by cgroup.
+        """
+        logging.info('Start')
+
+        err = ""
+        # Run available tests
+        for i in ['memory']:
+            try:
+                if self.modules.get_pwd(i):
+                    if (eval ("self.test_%s()" % i)):
+                        err += "%s, " % i
+                else:
+                    logging.error("CGROUP: Skipping test_%s, module not "
+                                  "available/mounted", i)
+                    err += "%s, " % i
+            except Exception, inst:
+                logging.error("CGROUP: test_%s fatal failure: %s", i, inst)
+                err += "%s, " % i
+
+        if err:
+            raise error.TestFail('CGROUP: Some subtests failed (%s)' % err[:-2])
+
+
+    def setup(self):
+        """
+        Setup
+        """
+        logging.info('Setup')
+
+        self._client = os.path.join(self.bindir, "cgroup_client.py")
+
+        _modules = ['cpuset', 'ns', 'cpu', 'cpuacct', 'memory', 'devices',
+                    'freezer', 'net_cls', 'blkio']
+        if (self.modules.init(_modules) <= 0):
+            raise error.TestFail('Can\'t mount any cgroup modules')
+
+
+    def cleanup(self):
+        """
+        Unmount all cgroups and remove directories
+        """
+        logging.info('Cleanup')
+        self.modules.cleanup()
+
+
+    #############################
+    # TESTS
+    #############################
+    def test_memory(self):
+        """
+        Memory test
+        """
+        # Preparation
+        logging.info("Entering 'test_memory'")
+        item = CG('memory', self._client)
+        if item.initialize(self.modules):
+            logging.error("test_memory: cgroup init failed")
+            return -1
+
+        if item.smoke_test():
+            logging.error("test_memory: smoke_test failed")
+            return -1
+
+        pwd = item.mk_cgroup()
+        if pwd == None:
+            logging.error("test_memory: Can't create cgroup")
+            return -1
+
+        logging.debug("test_memory: Memory filling test")
+
+        f = open('/proc/meminfo','r')
+        mem = f.readline()
+        while not mem.startswith("MemFree"):
+            mem = f.readline()
+        # Use only 1G or max of the free memory
+        mem = min(int(mem.split()[1])/1024, 1024)
+        mem = max(mem, 100) # at least 100M
+        if (item.get_property("memory.memsw.limit_in_bytes", supress=True)
+                                                                    != None):
+            memsw = True
+            # Clear swap
+            os.system("swapoff -a")
+            os.system("swapon -a")
+            f.seek(0)
+            swap = f.readline()
+            while not swap.startswith("SwapTotal"):
+                swap = f.readline()
+            swap = int(swap.split()[1])/1024
+            if swap < mem / 2:
+                logging.error("Not enough swap memory to test 'memsw'")
+                memsw = False
+        else:
+            # Doesn't support swap+memory limitation, disable swap
+            logging.info("'memsw' not supported")
+            os.system("swapoff -a")
+            memsw = False
+        logging.debug("test_memory: Initializition passed")
+
+        ################################################
+        # Fill the memory without cgroup limitation
+        # Should pass
+        ################################################
+        logging.debug("test_memory: Memfill WO cgroup")
+        ps = item.test("memfill %d" % mem)
+        ps.stdin.write('\n')
+        i = 0
+        while ps.poll() == None:
+            if i > 60:
+                break
+            i += 1
+            time.sleep(1)
+        if i > 60:
+            logging.error("test_memory: Memory filling failed (WO cgroup)")
+            ps.terminate()
+            return -1
+        if not ps.stdout.readlines()[-1].startswith("PASS"):
+            logging.error("test_memory: Unsuccessful memory filling "
+                          "(WO cgroup)")
+            return -1
+        logging.debug("test_memory: Memfill WO cgroup passed")
+
+        ################################################
+        # Fill the memory with 1/2 memory limit
+        # memsw: should swap out part of the process and pass
+        # WO memsw: should fail (SIGKILL)
+        ################################################
+        logging.debug("test_memory: Memfill mem only limit")
+        ps = item.test("memfill %d" % mem)
+        if item.set_cgroup(ps.pid, pwd):
+            logging.error("test_memory: Could not set cgroup")
+            return -1
+        if item.set_property("memory.limit_in_bytes", (1024*1024*mem/2), pwd):
+            logging.error("test_memory: Could not set mem limit (mem)")
+            return -1
+        ps.stdin.write('\n')
+        i = 0
+        while ps.poll() == None:
+            if i > 60:
+                break
+            i += 1
+            time.sleep(1)
+        if i > 60:
+            logging.error("test_memory: Memory filling failed (mem)")
+            ps.terminate()
+            return -1
+        out = ps.stdout.readlines()
+        if len(out) < 2:
+            logging.error("test_memory: Process failed; output:\n%s", out)
+            return -1
+        if memsw:
+            if not out[-1].startswith("PASS"):
+                logging.error("test_memory: Unsuccessful memory filling (mem)")
+                logging.error("test_memory: cgroup_client.py returned %d; "
+                              "output:\n%s", ps.poll(), out)
+                return -1
+        else:
+            if out[-1].startswith("PASS"):
+                logging.error("test_memory: Unexpected memory filling (mem)")
+                return -1
+            else:
+                filled = int(out[-2].split()[1][:-1])
+                if mem/2 > 1.5*filled:
+                    logging.error("test_memory: Limit = %dM, Filled = %dM (+ "
+                               "python overhead upto 1/3 (mem)", mem/2, filled)
+                else:
+                    logging.debug("test_memory: Limit = %dM, Filled = %dM (+ "
+                               "python overhead upto 1/3 (mem)", mem/2, filled)
+        logging.debug("test_memory: Memfill mem only cgroup passed")
+
+        ################################################
+        # Fill the memory with 1/2 memory+swap limit
+        # Should fail
+        ################################################
+        logging.debug("test_memory: Memfill mem + swap limit")
+        if memsw:
+            ps = item.test("memfill %d" % mem)
+            if item.set_cgroup(ps.pid, pwd):
+                logging.error("test_memory: Could not set cgroup (memsw)")
+                return -1
+            if item.set_property("memory.memsw.limit_in_bytes",
+                                 (1024*1024*mem/2), pwd):
+                logging.error("test_memory: Could not set mem limit (memsw)")
+                return -1
+            ps.stdin.write('\n')
+            i = 0
+            while ps.poll() == None:
+                if i > 60:
+                    break
+                i += 1
+                time.sleep(1)
+            if i > 60:
+                logging.error("test_memory: Memory filling failed (mem)")
+                ps.terminate()
+                return -1
+            out = ps.stdout.readlines()
+            if len(out) < 2:
+                logging.error("test_memory: Process failed; output:\n%s", out)
+                return -1
+            if out[-1].startswith("PASS"):
+                logging.error("test_memory: Unexpected memory filling (memsw)",
+                              mem)
+                return -1
+            else:
+                filled = int(out[-2].split()[1][:-1])
+                if mem/2 > 1.5*filled:
+                    logging.error("test_memory: Limit = %dM, Filled = %dM (+ "
+                              "python overhead upto 1/3 (memsw)", mem/2, filled)
+                else:
+                    logging.debug("test_memory: Limit = %dM, Filled = %dM (+ "
+                              "python overhead upto 1/3 (memsw)", mem/2, filled)
+            logging.debug("test_memory: Memfill mem+swap cgroup passed")
+
+        # cleanup
+        logging.debug("test_memory: Cleanup")
+        if item.rm_cgroup(pwd):
+            logging.error("test_memory: Can't remove cgroup directory")
+            return -1
+        os.system("swapon -a")
+
+        logging.info("Leaving 'test_memory': PASSED")
+        return 0
diff --git a/client/tests/cgroup/cgroup_client.py b/client/tests/cgroup/cgroup_client.py
new file mode 100755
index 0000000..ff098ef
--- /dev/null
+++ b/client/tests/cgroup/cgroup_client.py
@@ -0,0 +1,116 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""
+Interactive python script for testing cgroups
+
+@copyright: 2011 Red Hat Inc.
+@author: Lukas Doktor <ldoktor@redhat.com>
+"""
+import array, sys, time, math
+
+def test_smoke():
+    """
+    SIGSTOP the process and after SIGCONT exits.
+    """
+    print "TEST: smoke"
+    print "TEST: wait for input"
+    raw_input()
+    print "PASS: smoke"
+
+
+def test_memfill(size=1024):
+    """
+    SIGSTOP and after SIGCONT fills the memory up to size size.
+    """
+    print "TEST: memfill (%dM)" % size
+    print "TEST: wait for input"
+    raw_input()
+    mem = array.array('B')
+    buf = ""
+    for i in range(1024*1024):
+        buf += '\x00'
+    for i in range(size):
+        mem.fromstring(buf)
+        #for j in range(1024*1024):
+        #    mem.append(0)
+        print "TEST: %dM" % i
+    print "PASS: memfill (%dM)" % size
+
+
+def test_cpu():
+    """
+    Stress the CPU
+    """
+    print "TEST: cpu"
+    print "TEST: wait for input"
+    raw_input()
+    while True:
+        for i in range (1000, 10000):
+            math.factorial(i)
+
+
+def test_devices_read():
+    """
+    Inf read from /dev/zero
+    """
+    print "TEST: devices read"
+    print "TEST: wait for input"
+    raw_input()
+
+    dev = open("/dev/zero", 'r')
+    while True:
+        print "TEST: tick"
+        dev.flush()
+        dev.read(1024*1024)
+        time.sleep(1)
+
+
+def test_devices_write():
+    """
+    Inf write into /dev/null device
+    """
+    print "TEST: devices write"
+    print "TEST: wait for input"
+    raw_input()
+
+    dev = open("/dev/null", 'w')
+    buf = ""
+    for _ in range(1024*1024):
+        buf += '\x00'
+    while True:
+        print "TEST: tick"
+        dev.write(buf)
+        dev.flush()
+        time.sleep(1)
+
+
+def main():
+    """
+    Main (infinite) loop.
+    """
+    if len(sys.argv) < 2:
+        print "FAIL: Incorrect usage"
+        return -1
+    if sys.argv[1] == "smoke":
+        test_smoke()
+    elif sys.argv[1] == "memfill":
+        if len(sys.argv) > 2:
+            test_memfill(int(sys.argv[2]))
+        else:
+            test_memfill()
+    elif sys.argv[1] == "cpu":
+        test_cpu()
+    elif sys.argv[1] == "devices":
+        if len(sys.argv) > 2:
+            if (sys.argv[2] == "write"):
+                test_devices_write()
+            else:
+                test_devices_read()
+        else:
+            test_devices_read()
+    else:
+        print "FAIL: No test specified"
+
+if __name__ == "__main__":
+    main()
+
diff --git a/client/tests/cgroup/cgroup_common.py b/client/tests/cgroup/cgroup_common.py
new file mode 100755
index 0000000..3fd1cf7
--- /dev/null
+++ b/client/tests/cgroup/cgroup_common.py
@@ -0,0 +1,327 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""
+Helpers for cgroup testing
+
+@copyright: 2011 Red Hat Inc.
+@author: Lukas Doktor <ldoktor@redhat.com>
+"""
+import os, logging
+import subprocess
+from tempfile import mkdtemp
+import time
+
+class Cgroup:
+    """
+    Cgroup handling class
+    """
+    def __init__(self, module, _client):
+        """
+        Constructor
+        @param module: Name of the cgroup module
+        @param _client: Test script pwd+name
+        """
+        self.module = module
+        self._client = _client
+        self.root = None
+
+
+    def initialize(self, modules):
+        """
+        Inicializes object for use
+        @param modules: array of all available cgroup modules
+        @return: 0 when PASSED
+        """
+        self.root = modules.get_pwd(self.module)
+        if self.root:
+            return 0
+        else:
+            logging.error("cg.initialize(): Module %s not found", self.module)
+            return -1
+        return 0
+
+
+    def mk_cgroup(self, root=None):
+        """
+        Creates new temporary cgroup
+        @param root: where to create this cgroup (default: self.root)
+        @return: 0 when PASSED
+        """
+        try:
+            if root:
+                pwd = mkdtemp(prefix='cgroup-', dir=root) + '/'
+            else:
+                pwd = mkdtemp(prefix='cgroup-', dir=self.root) + '/'
+        except Exception, inst:
+            logging.error("cg.mk_cgroup(): %s" , inst)
+            return None
+        return pwd
+
+
+    def rm_cgroup(self, pwd, supress=False):
+        """
+        Removes cgroup
+        @param pwd: cgroup directory
+        @param supress: supress output
+        @return: 0 when PASSED
+        """
+        try:
+            os.rmdir(pwd)
+        except Exception, inst:
+            if not supress:
+                logging.error("cg.rm_cgroup(): %s" , inst)
+            return -1
+        return 0
+
+
+    def test(self, cmd):
+        """
+        Executes cgroup_client.py with cmd parameter
+        @param cmd: command to be executed
+        @return: subprocess.Popen() process
+        """
+        logging.debug("cg.test(): executing paralel process '%s'" , cmd)
+        process = subprocess.Popen((self._client + ' ' + cmd), shell=True,
+                                stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+                                stderr=subprocess.PIPE, close_fds=True)
+        return process
+
+
+    def is_cgroup(self, pid, pwd):
+        """
+        Checks if the 'pid' process is in 'pwd' cgroup
+        @param pid: pid of the process
+        @param pwd: cgroup directory
+        @return: 0 when is 'pwd' member
+        """
+        if open(pwd+'/tasks').readlines().count("%d\n" % pid) > 0:
+            return 0
+        else:
+            return -1
+
+    def is_root_cgroup(self, pid):
+        """
+        Checks if the 'pid' process is in root cgroup (WO cgroup)
+        @param pid: pid of the process
+        @return: 0 when is 'root' member
+        """
+        return self.is_cgroup(pid, self.root)
+
+    def set_cgroup(self, pid, pwd):
+        """
+        Sets cgroup membership
+        @param pid: pid of the process
+        @param pwd: cgroup directory
+        @return: 0 when PASSED
+        """
+        try:
+            open(pwd+'/tasks', 'w').write(str(pid))
+        except Exception, inst:
+            logging.error("cg.set_cgroup(): %s" , inst)
+            return -1
+        if self.is_cgroup(pid, pwd):
+            logging.error("cg.set_cgroup(): Setting %d pid into %s cgroup "
+                          "failed", pid, pwd)
+            return -1
+        else:
+            return 0
+
+    def set_root_cgroup(self, pid):
+        """
+        Resets the cgroup membership (sets to root)
+        @param pid: pid of the process
+        @return: 0 when PASSED
+        """
+        return self.set_cgroup(pid, self.root)
+
+
+    def get_property(self, prop, pwd=None, supress=False):
+        """
+        Gets the property value
+        @param prop: property name (file)
+        @param pwd: cgroup directory
+        @param supress: supress the output
+        @return: String value or None when FAILED
+        """
+        if pwd == None:
+            pwd = self.root
+        try:
+            ret = open(pwd+prop, 'r').readlines()
+        except Exception, inst:
+            ret = None
+            if not supress:
+                logging.error("cg.get_property(): %s" , inst)
+        return ret
+
+
+    def set_property(self, prop, value, pwd=None, check=True):
+        """
+        Sets the property value
+        @param prop: property name (file)
+        @param value: desired value
+        @param pwd: cgroup directory
+        @param check: check the value after setup
+        @return: 0 when PASSED
+        """
+        value = str(value)
+        if pwd == None:
+            pwd = self.root
+        try:
+            open(pwd+prop, 'w').write(value)
+        except Exception, inst:
+            logging.error("cg.set_property(): %s" , inst)
+            return -1
+        if check:
+            # Get the first line - '\n'
+            _value = self.get_property(prop, pwd)[0][:-1]
+            if value != _value:
+                logging.error("cg.set_property(): Setting failed: desired = %s,"
+                              " real value = %s", value, _value)
+                return -1
+        return 0
+
+
+    def smoke_test(self):
+        """
+        Smoke test
+        Module independent basic tests
+        """
+        part = 0
+        pwd = self.mk_cgroup()
+        if pwd == None:
+            logging.error("cg.smoke_test[%d]: Can't create cgroup", part)
+            return -1
+
+        part += 1
+        ps = self.test("smoke")
+        if ps == None:
+            logging.error("cg.smoke_test[%d]: Couldn't create process", part)
+            return -1
+
+        part += 1
+        if (ps.poll() != None):
+            logging.error("cg.smoke_test[%d]: Process died unexpectidly", part)
+            return -1
+
+        # New process should be a root member
+        part += 1
+        if self.is_root_cgroup(ps.pid):
+            logging.error("cg.smoke_test[%d]: Process is not a root member",
+                          part)
+            return -1
+
+        # Change the cgroup
+        part += 1
+        if self.set_cgroup(ps.pid, pwd):
+            logging.error("cg.smoke_test[%d]: Could not set cgroup", part)
+            return -1
+
+        # Try to remove used cgroup
+        part += 1
+        if self.rm_cgroup(pwd, supress=True) == 0:
+            logging.error("cg.smoke_test[%d]: Unexpected successful deletion of"
+                          " the used cgroup", part)
+            return -1
+
+        # Return the process into the root cgroup
+        part += 1
+        if self.set_root_cgroup(ps.pid):
+            logging.error("cg.smoke_test[%d]: Could not return the root cgroup "
+                          "membership", part)
+            return -1
+
+        # It should be safe to remove the cgroup now
+        part += 1
+        if self.rm_cgroup(pwd):
+            logging.error("cg.smoke_test[%d]: Can't remove cgroup direcotry",
+                          part)
+            return -1
+
+        # Finish the process
+        part += 1
+        ps.stdin.write('\n')
+        time.sleep(2)
+        if (ps.poll() == None):
+            logging.error("cg.smoke_test[%d]: Process is not finished", part)
+            return -1
+
+        return 0
+
+
+class CgroupModules:
+    """
+    Handles the list of different cgroup filesystems
+    """
+    def __init__(self):
+        self.modules = []
+        self.modules.append([])
+        self.modules.append([])
+        self.modules.append([])
+        self.mountdir = mkdtemp(prefix='cgroup-') + '/'
+
+
+    def init(self, _modules):
+        """
+        Checks the mounted modules and if necessarily mounts them into tmp
+            mountdir.
+        @param _modules: desired modules
+        @return: Number of initialized modules
+        """
+        mounts = []
+        fp = open('/proc/mounts', 'r')
+        line = fp.readline().split()
+        while line:
+            if line[2] == 'cgroup':
+                mounts.append(line)
+            line = fp.readline().split()
+        fp.close()
+
+        for module in _modules:
+            # Is it already mounted?
+            i = False
+            for mount in mounts:
+                if mount[3].find(module) != -1:
+                    self.modules[0].append(module)
+                    self.modules[1].append(mount[1]+'/')
+                    self.modules[2].append(False)
+                    i = True
+                    break
+
+            if not i:
+                # Not yet mounted
+                os.mkdir(self.mountdir+module)
+                logging.info('mount -t cgroup -o %s %s %s', module, module,
+                             self.mountdir+module)
+                if (os.system('mount -t cgroup -o %s %s %s'
+                                    % (module, module, self.mountdir+module)) == 0):
+                    self.modules[0].append(module)
+                    self.modules[1].append(self.mountdir+module)
+                    self.modules[2].append(True)
+                else:
+                    logging.error("Module '%s' is not available, mount failed",
+                                    module)
+        return len(self.modules[0])
+
+
+    def cleanup(self):
+        """
+        Unmount all cgroups and remove the mountdir
+        """
+        for i in range(len(self.modules[0])):
+            if self.modules[2][i]:
+                os.system('umount %s -l' % self.modules[1][i])
+        os.system('rm -rf %s' % self.mountdir)
+
+
+    def get_pwd(self, module):
+        """
+        Returns the mount directory of 'module'
+        @param module: desired module (memory, ...)
+        @return: mount directory of 'module' or None
+        """
+        try:
+            i = self.modules[0].index(module)
+        except Exception, inst:
+            logging.error("module %s not found: %s", module, inst)
+            return None
+        return self.modules[1][i]
diff --git a/client/tests/cgroup/control b/client/tests/cgroup/control
new file mode 100644
index 0000000..86aec06
--- /dev/null
+++ b/client/tests/cgroup/control
@@ -0,0 +1,12 @@
+AUTHOR = "Lukas Doktor <ldoktor@redhat.com>"
+NAME = "Cgroup"
+TIME = "SHORT"
+TEST_CATEGORY = "Functional"
+TEST_CLASS = "General"
+TEST_TYPE = "client"
+
+DOC = """
+This test checks basic functionality of cgroups
+"""
+
+job.run_test('cgroup')
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/4] bugfixies
  2011-08-15 12:23 [autotest][PATCH] cgroup test + modifications Lukas Doktor
  2011-08-15 12:23 ` [PATCH 1/4] [NEW] cgroup test * general smoke_test + module dependend subtests (memory test included) * library for future use in other tests (kvm) Lukas Doktor
@ 2011-08-15 12:23 ` Lukas Doktor
  2011-08-15 12:23 ` [PATCH 3/4] cpuset test Lukas Doktor
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Lukas Doktor @ 2011-08-15 12:23 UTC (permalink / raw)
  To: autotest, kvm, kvm-autotest, fyang, lmr, ldoktor, jzupka

* slight modification of the subtests executions
* modified clean-up function
* raise errors instead of returns
* more failure checking

Signed-off-by: Lukas Doktor <ldoktor@redhat.com>
---
 client/tests/cgroup/cgroup.py        |  116 +++++++++++++++++----------------
 client/tests/cgroup/cgroup_client.py |    3 +-
 client/tests/cgroup/cgroup_common.py |   45 +++++++++++++-
 3 files changed, 106 insertions(+), 58 deletions(-)

diff --git a/client/tests/cgroup/cgroup.py b/client/tests/cgroup/cgroup.py
index 112f012..45636f2 100755
--- a/client/tests/cgroup/cgroup.py
+++ b/client/tests/cgroup/cgroup.py
@@ -23,20 +23,24 @@ class cgroup(test.test):
         err = ""
         # Run available tests
         for i in ['memory']:
+            logging.info("---< 'test_%s' START >---", i)
             try:
-                if self.modules.get_pwd(i):
-                    if (eval ("self.test_%s()" % i)):
-                        err += "%s, " % i
-                else:
-                    logging.error("CGROUP: Skipping test_%s, module not "
-                                  "available/mounted", i)
-                    err += "%s, " % i
+                if not self.modules.get_pwd(i):
+                    raise error.TestFail("module not available/mounted")
+                eval ("self.test_%s()" % i)
+                logging.info("---< 'test_%s' PASSED >---", i)
+            except AttributeError:
+                err += "%s, " % i
+                logging.error("test_%s: Test doesn't exist", i)
+                logging.info("---< 'test_%s' FAILED >---", i)
             except Exception, inst:
-                logging.error("CGROUP: test_%s fatal failure: %s", i, inst)
                 err += "%s, " % i
+                logging.error("test_%s: %s", i, inst)
+                logging.info("---< 'test_%s' FAILED >---", i)
 
         if err:
-            raise error.TestFail('CGROUP: Some subtests failed (%s)' % err[:-2])
+            logging.error('Some subtests failed (%s)' % err[:-2])
+            raise error.TestFail('Some subtests failed (%s)' % err[:-2])
 
 
     def setup(self):
@@ -68,21 +72,31 @@ class cgroup(test.test):
         """
         Memory test
         """
+        def cleanup(supress=False):
+            # cleanup
+            logging.debug("test_memory: Cleanup")
+            err = ""
+            if item.rm_cgroup(pwd):
+                err += "\nCan't remove cgroup directory"
+
+            os.system("swapon -a")
+            if err:
+                if supress:
+                    logging.warn("Some parts of cleanup failed%s" % err)
+                else:
+                    raise error.TestFail("Some parts of cleanup failed%s" % err)
+
         # Preparation
-        logging.info("Entering 'test_memory'")
         item = CG('memory', self._client)
         if item.initialize(self.modules):
-            logging.error("test_memory: cgroup init failed")
-            return -1
+            raise error.TestFail("cgroup init failed")
 
         if item.smoke_test():
-            logging.error("test_memory: smoke_test failed")
-            return -1
+            raise error.TestFail("smoke_test failed")
 
         pwd = item.mk_cgroup()
         if pwd == None:
-            logging.error("test_memory: Can't create cgroup")
-            return -1
+            raise error.TestFail("Can't create cgroup")
 
         logging.debug("test_memory: Memory filling test")
 
@@ -128,13 +142,15 @@ class cgroup(test.test):
             i += 1
             time.sleep(1)
         if i > 60:
-            logging.error("test_memory: Memory filling failed (WO cgroup)")
             ps.terminate()
-            return -1
-        if not ps.stdout.readlines()[-1].startswith("PASS"):
-            logging.error("test_memory: Unsuccessful memory filling "
+            raise error.TestFail("Memory filling failed (WO cgroup)")
+        out = ps.stdout.readlines()
+        if (len(out) < 2) or (ps.poll() != 0):
+            raise error.TestFail("Process failed (WO cgroup); output:\n%s"
+                          "\nReturn: %d", out, ps.poll())
+        if not out[-1].startswith("PASS"):
+            raise error.TestFail("Unsuccessful memory filling "
                           "(WO cgroup)")
-            return -1
         logging.debug("test_memory: Memfill WO cgroup passed")
 
         ################################################
@@ -145,11 +161,9 @@ class cgroup(test.test):
         logging.debug("test_memory: Memfill mem only limit")
         ps = item.test("memfill %d" % mem)
         if item.set_cgroup(ps.pid, pwd):
-            logging.error("test_memory: Could not set cgroup")
-            return -1
-        if item.set_property("memory.limit_in_bytes", (1024*1024*mem/2), pwd):
-            logging.error("test_memory: Could not set mem limit (mem)")
-            return -1
+            raise error.TestFail("Could not set cgroup")
+        if item.set_prop("memory.limit_in_bytes", ("%dM" % (mem/2)), pwd):
+            raise error.TestFail("Could not set mem limit (mem)")
         ps.stdin.write('\n')
         i = 0
         while ps.poll() == None:
@@ -158,23 +172,20 @@ class cgroup(test.test):
             i += 1
             time.sleep(1)
         if i > 60:
-            logging.error("test_memory: Memory filling failed (mem)")
             ps.terminate()
-            return -1
+            raise error.TestFail("Memory filling failed (mem)")
         out = ps.stdout.readlines()
-        if len(out) < 2:
-            logging.error("test_memory: Process failed; output:\n%s", out)
-            return -1
+        if (len(out)) < 2 or (ps.poll() != 0):
+            raise error.TestFail("Process failed (mem); output:\n%s"
+                          "\nReturn: %d", out, ps.poll())
         if memsw:
             if not out[-1].startswith("PASS"):
-                logging.error("test_memory: Unsuccessful memory filling (mem)")
                 logging.error("test_memory: cgroup_client.py returned %d; "
                               "output:\n%s", ps.poll(), out)
-                return -1
+                raise error.TestFail("Unsuccessful memory filling (mem)")
         else:
             if out[-1].startswith("PASS"):
-                logging.error("test_memory: Unexpected memory filling (mem)")
-                return -1
+                raise error.TestFail("Unexpected memory filling (mem)")
             else:
                 filled = int(out[-2].split()[1][:-1])
                 if mem/2 > 1.5*filled:
@@ -193,12 +204,9 @@ class cgroup(test.test):
         if memsw:
             ps = item.test("memfill %d" % mem)
             if item.set_cgroup(ps.pid, pwd):
-                logging.error("test_memory: Could not set cgroup (memsw)")
-                return -1
-            if item.set_property("memory.memsw.limit_in_bytes",
-                                 (1024*1024*mem/2), pwd):
-                logging.error("test_memory: Could not set mem limit (memsw)")
-                return -1
+                raise error.TestFail("Could not set cgroup (memsw)")
+            if item.set_prop("memory.memsw.limit_in_bytes", "%dM"%(mem/2), pwd):
+                raise error.TestFail("Could not set mem limit (memsw)")
             ps.stdin.write('\n')
             i = 0
             while ps.poll() == None:
@@ -207,17 +215,15 @@ class cgroup(test.test):
                 i += 1
                 time.sleep(1)
             if i > 60:
-                logging.error("test_memory: Memory filling failed (mem)")
                 ps.terminate()
-                return -1
+                raise error.TestFail("Memory filling failed (mem)")
             out = ps.stdout.readlines()
-            if len(out) < 2:
-                logging.error("test_memory: Process failed; output:\n%s", out)
-                return -1
+            if (len(out) < 2) or (ps.poll() != 0):
+                raise error.TestFail("Process failed (memsw); output:\n%s"
+                              "\nReturn: %d", out, ps.poll())
             if out[-1].startswith("PASS"):
-                logging.error("test_memory: Unexpected memory filling (memsw)",
+                raise error.TestFail("Unexpected memory filling (memsw)",
                               mem)
-                return -1
             else:
                 filled = int(out[-2].split()[1][:-1])
                 if mem/2 > 1.5*filled:
@@ -228,12 +234,10 @@ class cgroup(test.test):
                               "python overhead upto 1/3 (memsw)", mem/2, filled)
             logging.debug("test_memory: Memfill mem+swap cgroup passed")
 
-        # cleanup
-        logging.debug("test_memory: Cleanup")
-        if item.rm_cgroup(pwd):
-            logging.error("test_memory: Can't remove cgroup directory")
-            return -1
-        os.system("swapon -a")
+        ################################################
+        # CLEANUP
+        ################################################
+        cleanup()
+
+
 
-        logging.info("Leaving 'test_memory': PASSED")
-        return 0
diff --git a/client/tests/cgroup/cgroup_client.py b/client/tests/cgroup/cgroup_client.py
index ff098ef..03553c4 100755
--- a/client/tests/cgroup/cgroup_client.py
+++ b/client/tests/cgroup/cgroup_client.py
@@ -6,7 +6,7 @@ Interactive python script for testing cgroups
 @copyright: 2011 Red Hat Inc.
 @author: Lukas Doktor <ldoktor@redhat.com>
 """
-import array, sys, time, math
+import array, sys, time, math, os
 
 def test_smoke():
     """
@@ -34,6 +34,7 @@ def test_memfill(size=1024):
         #for j in range(1024*1024):
         #    mem.append(0)
         print "TEST: %dM" % i
+        sys.stdout.flush()
     print "PASS: memfill (%dM)" % size
 
 
diff --git a/client/tests/cgroup/cgroup_common.py b/client/tests/cgroup/cgroup_common.py
index 3fd1cf7..6cc8089 100755
--- a/client/tests/cgroup/cgroup_common.py
+++ b/client/tests/cgroup/cgroup_common.py
@@ -135,13 +135,30 @@ class Cgroup:
         return self.set_cgroup(pid, self.root)
 
 
+    def get_prop(self, prop, pwd=None, supress=False):
+        """
+        Gets one line of the property value
+        @param prop: property name (file)
+        @param pwd: cgroup directory
+        @param supress: supress the output
+        @return: String value or None when FAILED
+        """
+        tmp = self.get_property(prop, pwd, supress)
+        if tmp:
+            if tmp[0][-1] == '\n':
+                tmp[0] = tmp[0][:-1]
+            return tmp[0]
+        else:
+            return None
+
+
     def get_property(self, prop, pwd=None, supress=False):
         """
         Gets the property value
         @param prop: property name (file)
         @param pwd: cgroup directory
         @param supress: supress the output
-        @return: String value or None when FAILED
+        @return: [] values or None when FAILED
         """
         if pwd == None:
             pwd = self.root
@@ -154,6 +171,32 @@ class Cgroup:
         return ret
 
 
+    def set_prop(self, prop, value, pwd=None, check=True):
+        """
+        Sets the one-line property value concerning the K,M,G postfix
+        @param prop: property name (file)
+        @param value: desired value
+        @param pwd: cgroup directory
+        @param check: check the value after setup
+        @return: 0 when PASSED
+        """
+        _value = value
+        try:
+            value = str(value)
+            if value[-1] == '\n':
+                value = value[:-1]
+            if value[-1] == 'K':
+                value = int(value[:-1]) * 1024
+            elif value[-1] == 'M':
+                value = int(value[:-1]) * 1048576
+            elif value[-1] == 'G':
+                value = int(value[:-1]) * 1073741824
+        except:
+            logging.error("cg.set_prop() fallback into cg.set_property.")
+            value = _value
+        return self.set_property(prop, value, pwd, check)
+
+
     def set_property(self, prop, value, pwd=None, check=True):
         """
         Sets the property value
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/4] cpuset test
  2011-08-15 12:23 [autotest][PATCH] cgroup test + modifications Lukas Doktor
  2011-08-15 12:23 ` [PATCH 1/4] [NEW] cgroup test * general smoke_test + module dependend subtests (memory test included) * library for future use in other tests (kvm) Lukas Doktor
  2011-08-15 12:23 ` [PATCH 2/4] bugfixies Lukas Doktor
@ 2011-08-15 12:23 ` Lukas Doktor
  2011-08-15 12:23 ` [PATCH 4/4] [FIX] Use file instead of PIPE in memfill test (problem with sync) Lukas Doktor
  2011-09-01  8:03 ` [autotest][PATCH] cgroup test + modifications Jan Stancek
  4 siblings, 0 replies; 8+ messages in thread
From: Lukas Doktor @ 2011-08-15 12:23 UTC (permalink / raw)
  To: autotest, kvm, kvm-autotest, fyang, lmr, ldoktor, jzupka

Tests the cgroup cpuset (cpu affinity) functionality. It spawn no_cpus+1 cpu-intensive proces', limits the cpu affinity to cpu0 using cgroups and verifies. Than it do the same on all cpus except the cpu0.

Signed-off-by: Lukas Doktor <ldoktor@redhat.com>
---
 client/tests/cgroup/cgroup.py |  161 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 160 insertions(+), 1 deletions(-)

diff --git a/client/tests/cgroup/cgroup.py b/client/tests/cgroup/cgroup.py
index 45636f2..dc5a1b3 100755
--- a/client/tests/cgroup/cgroup.py
+++ b/client/tests/cgroup/cgroup.py
@@ -22,7 +22,7 @@ class cgroup(test.test):
 
         err = ""
         # Run available tests
-        for i in ['memory']:
+        for i in ['memory', 'cpuset']:
             logging.info("---< 'test_%s' START >---", i)
             try:
                 if not self.modules.get_pwd(i):
@@ -241,3 +241,162 @@ class cgroup(test.test):
 
 
 
+    def test_cpuset(self):
+        """
+        Cpuset test
+        1) Initiate CPU load on CPU0, than spread into CPU* - CPU0
+        """
+        class per_cpu_load:
+            """
+            Handles the per_cpu_load stats
+            self.values [cpus, cpu0, cpu1, ...]
+            """
+            def __init__(self):
+                """
+                Init
+                """
+                self.values = []
+                self.f = open('/proc/stat', 'r')
+                line = self.f.readline()
+                while line:
+                    if line.startswith('cpu'):
+                        self.values.append(int(line.split()[1]))
+                    else:
+                        break
+                    line = self.f.readline()
+
+            def reload(self):
+                """
+                Reload current values
+                """
+                self.values = self.get()
+
+            def get(self):
+                """
+                Get the current values
+                @return vals: array of current values [cpus, cpu0, cpu1..]
+                """
+                self.f.seek(0)
+                self.f.flush()
+                vals = []
+                for i in range(len(self.values)):
+                    vals.append(int(self.f.readline().split()[1]))
+                return vals
+
+            def tick(self):
+                """
+                Reload values and returns the load between the last tick/reload
+                @return vals: array of load between ticks/reloads
+                              values [cpus, cpu0, cpu1..]
+                """
+                vals = self.get()
+                ret = []
+                for i in range(len(self.values)):
+                    ret.append(vals[i] - self.values[i])
+                self.values = vals
+                return ret
+
+        def cleanup(supress=False):
+            # cleanup
+            logging.debug("test_cpuset: Cleanup")
+            err = ""
+            try:
+                for task in tasks:
+                    for i in range(10):
+                        task.terminate()
+                        if task.poll() != None:
+                            break
+                        time.sleep(1)
+                    if i >= 9:
+                        logging.error("test_cpuset: Subprocess didn't finish")
+            except Exception, inst:
+                err += "\nCan't terminate tasks: %s" % inst
+            if item.rm_cgroup(pwd):
+                err += "\nCan't remove cgroup direcotry"
+            if err:
+                if supress:
+                    logging.warn("Some parts of cleanup failed%s" % err)
+                else:
+                    raise error.TestFail("Some parts of cleanup failed%s" % err)
+
+        # Preparation
+        item = CG('cpuset', self._client)
+        if item.initialize(self.modules):
+            raise error.TestFail("cgroup init failed")
+
+        # FIXME: new cpuset cgroup doesn't have any mems and cpus assigned
+        # thus smoke_test won't work
+        #if item.smoke_test():
+        #    raise error.TestFail("smoke_test failed")
+
+        try:
+            # Available cpus: cpuset.cpus = "0-$CPUS\n"
+            no_cpus = int(item.get_prop("cpuset.cpus").split('-')[1]) + 1
+        except:
+            raise error.TestFail("Failed to get no_cpus or no_cpus = 1")
+
+        pwd = item.mk_cgroup()
+        if pwd == None:
+            raise error.TestFail("Can't create cgroup")
+        # FIXME: new cpuset cgroup doesn't have any mems and cpus assigned
+        try:
+            tmp = item.get_prop("cpuset.cpus")
+            item.set_property("cpuset.cpus", tmp, pwd)
+            tmp = item.get_prop("cpuset.mems")
+            item.set_property("cpuset.mems", tmp, pwd)
+        except:
+            cleanup(True)
+            raise error.TestFail("Failed to set cpus and mems of"
+                                 "a new cgroup")
+
+        ################################################
+        # Cpu allocation test
+        # Use cpu0 and verify, than all cpu* - cpu0 and verify
+        ################################################
+        logging.debug("test_cpuset: Cpu allocation test")
+
+        tasks = []
+        # Run no_cpus + 1 jobs
+        for i in range(no_cpus + 1):
+            tasks.append(item.test("cpu"))
+            if item.set_cgroup(tasks[i].pid, pwd):
+                cleanup(True)
+                raise error.TestFail("Failed to set cgroup")
+            tasks[i].stdin.write('\n')
+        stats = per_cpu_load()
+        # Use only the first CPU
+        item.set_property("cpuset.cpus", 0, pwd)
+        stats.reload()
+        time.sleep(10)
+        # [0] = all cpus
+        s1 = stats.tick()[1:]
+        s2 = s1[1:]
+        s1 = s1[0]
+        for _s in s2:
+            if s1 < _s:
+                cleanup(True)
+                raise error.TestFail("Unused processor had higher utilization\n"
+                                     "used cpu: %s, remaining cpus: %s"
+                                     % (s1, s2))
+
+        if no_cpus == 2:
+            item.set_property("cpuset.cpus", "1", pwd)
+        else:
+            item.set_property("cpuset.cpus", "1-%d"%(no_cpus-1), pwd)
+        stats.reload()
+        time.sleep(10)
+        s1 = stats.tick()[1:]
+        s2 = s1[0]
+        s1 = s1[1:]
+        for _s in s1:
+            if s2 > _s:
+                cleanup(True)
+                raise error.TestFail("Unused processor had higher utilization\n"
+                                     "used cpus: %s, remaining cpu: %s"
+                                     % (s1, s2))
+        logging.debug("test_cpuset: Cpu allocation test passed")
+
+        ################################################
+        # CLEANUP
+        ################################################
+        cleanup()
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/4] [FIX] Use file instead of PIPE in memfill test (problem with sync)
  2011-08-15 12:23 [autotest][PATCH] cgroup test + modifications Lukas Doktor
                   ` (2 preceding siblings ...)
  2011-08-15 12:23 ` [PATCH 3/4] cpuset test Lukas Doktor
@ 2011-08-15 12:23 ` Lukas Doktor
  2011-09-01  8:03 ` [autotest][PATCH] cgroup test + modifications Jan Stancek
  4 siblings, 0 replies; 8+ messages in thread
From: Lukas Doktor @ 2011-08-15 12:23 UTC (permalink / raw)
  To: autotest, kvm, kvm-autotest, fyang, lmr, ldoktor, jzupka

Signed-off-by: Lukas Doktor <ldoktor@redhat.com>
---
 client/tests/cgroup/cgroup.py        |   44 +++++++++++++++---------
 client/tests/cgroup/cgroup_client.py |   61 ++++++++++++++++++++-------------
 2 files changed, 64 insertions(+), 41 deletions(-)

diff --git a/client/tests/cgroup/cgroup.py b/client/tests/cgroup/cgroup.py
index dc5a1b3..0f56ad5 100755
--- a/client/tests/cgroup/cgroup.py
+++ b/client/tests/cgroup/cgroup.py
@@ -4,6 +4,7 @@ import os, logging
 import time
 from cgroup_common import Cgroup as CG
 from cgroup_common import CgroupModules
+from tempfile import NamedTemporaryFile
 
 class cgroup(test.test):
     """
@@ -13,7 +14,6 @@ class cgroup(test.test):
     _client = ""
     modules = CgroupModules()
 
-
     def run_once(self):
         """
 	    Try to access different resources which are restricted by cgroup.
@@ -80,6 +80,7 @@ class cgroup(test.test):
                 err += "\nCan't remove cgroup directory"
 
             os.system("swapon -a")
+
             if err:
                 if supress:
                     logging.warn("Some parts of cleanup failed%s" % err)
@@ -126,6 +127,8 @@ class cgroup(test.test):
             logging.info("'memsw' not supported")
             os.system("swapoff -a")
             memsw = False
+        outf = NamedTemporaryFile('w+', prefix="cgroup_client-",
+                                       dir="/tmp")
         logging.debug("test_memory: Initializition passed")
 
         ################################################
@@ -133,7 +136,7 @@ class cgroup(test.test):
         # Should pass
         ################################################
         logging.debug("test_memory: Memfill WO cgroup")
-        ps = item.test("memfill %d" % mem)
+        ps = item.test("memfill %d %s" % (mem, outf.name))
         ps.stdin.write('\n')
         i = 0
         while ps.poll() == None:
@@ -144,10 +147,12 @@ class cgroup(test.test):
         if i > 60:
             ps.terminate()
             raise error.TestFail("Memory filling failed (WO cgroup)")
-        out = ps.stdout.readlines()
+        outf.seek(0)
+        outf.flush()
+        out = outf.readlines()
         if (len(out) < 2) or (ps.poll() != 0):
             raise error.TestFail("Process failed (WO cgroup); output:\n%s"
-                          "\nReturn: %d", out, ps.poll())
+                          "\nReturn: %d" % (out, ps.poll()))
         if not out[-1].startswith("PASS"):
             raise error.TestFail("Unsuccessful memory filling "
                           "(WO cgroup)")
@@ -159,7 +164,7 @@ class cgroup(test.test):
         # WO memsw: should fail (SIGKILL)
         ################################################
         logging.debug("test_memory: Memfill mem only limit")
-        ps = item.test("memfill %d" % mem)
+        ps = item.test("memfill %d %s" % (mem, outf.name))
         if item.set_cgroup(ps.pid, pwd):
             raise error.TestFail("Could not set cgroup")
         if item.set_prop("memory.limit_in_bytes", ("%dM" % (mem/2)), pwd):
@@ -167,17 +172,19 @@ class cgroup(test.test):
         ps.stdin.write('\n')
         i = 0
         while ps.poll() == None:
-            if i > 60:
+            if i > 120:
                 break
             i += 1
             time.sleep(1)
-        if i > 60:
+        if i > 120:
             ps.terminate()
             raise error.TestFail("Memory filling failed (mem)")
-        out = ps.stdout.readlines()
-        if (len(out)) < 2 or (ps.poll() != 0):
+        outf.seek(0)
+        outf.flush()
+        out = outf.readlines()
+        if (len(out) < 2):
             raise error.TestFail("Process failed (mem); output:\n%s"
-                          "\nReturn: %d", out, ps.poll())
+                          "\nReturn: %d" % (out, ps.poll()))
         if memsw:
             if not out[-1].startswith("PASS"):
                 logging.error("test_memory: cgroup_client.py returned %d; "
@@ -199,10 +206,11 @@ class cgroup(test.test):
         ################################################
         # Fill the memory with 1/2 memory+swap limit
         # Should fail
+        # (memory.limit_in_bytes have to be set prior to this test)
         ################################################
-        logging.debug("test_memory: Memfill mem + swap limit")
         if memsw:
-            ps = item.test("memfill %d" % mem)
+            logging.debug("test_memory: Memfill mem + swap limit")
+            ps = item.test("memfill %d %s" % (mem, outf.name))
             if item.set_cgroup(ps.pid, pwd):
                 raise error.TestFail("Could not set cgroup (memsw)")
             if item.set_prop("memory.memsw.limit_in_bytes", "%dM"%(mem/2), pwd):
@@ -210,17 +218,19 @@ class cgroup(test.test):
             ps.stdin.write('\n')
             i = 0
             while ps.poll() == None:
-                if i > 60:
+                if i > 120:
                     break
                 i += 1
                 time.sleep(1)
-            if i > 60:
+            if i > 120:
                 ps.terminate()
                 raise error.TestFail("Memory filling failed (mem)")
-            out = ps.stdout.readlines()
-            if (len(out) < 2) or (ps.poll() != 0):
+            outf.seek(0)
+            outf.flush()
+            out = outf.readlines()
+            if (len(out) < 2):
                 raise error.TestFail("Process failed (memsw); output:\n%s"
-                              "\nReturn: %d", out, ps.poll())
+                              "\nReturn: %d" % (out, ps.poll()))
             if out[-1].startswith("PASS"):
                 raise error.TestFail("Unexpected memory filling (memsw)",
                               mem)
diff --git a/client/tests/cgroup/cgroup_client.py b/client/tests/cgroup/cgroup_client.py
index 03553c4..ab7311a 100755
--- a/client/tests/cgroup/cgroup_client.py
+++ b/client/tests/cgroup/cgroup_client.py
@@ -7,8 +7,9 @@ Interactive python script for testing cgroups
 @author: Lukas Doktor <ldoktor@redhat.com>
 """
 import array, sys, time, math, os
+from tempfile import mktemp
 
-def test_smoke():
+def test_smoke(args):
     """
     SIGSTOP the process and after SIGCONT exits.
     """
@@ -18,12 +19,20 @@ def test_smoke():
     print "PASS: smoke"
 
 
-def test_memfill(size=1024):
+def test_memfill(args):
     """
     SIGSTOP and after SIGCONT fills the memory up to size size.
     """
+    size = 1024
+    f = sys.stdout
+    if args:
+        size = int(args[0])
+        if len(args) > 1:
+            f = open(args[1], 'w', 0)
     print "TEST: memfill (%dM)" % size
-    print "TEST: wait for input"
+    print "Redirecting to: %s" % f.name
+    f.write("TEST: memfill (%dM)\n" % size)
+    f.write("TEST: wait for input\n")
     raw_input()
     mem = array.array('B')
     buf = ""
@@ -31,14 +40,16 @@ def test_memfill(size=1024):
         buf += '\x00'
     for i in range(size):
         mem.fromstring(buf)
-        #for j in range(1024*1024):
-        #    mem.append(0)
-        print "TEST: %dM" % i
-        sys.stdout.flush()
-    print "PASS: memfill (%dM)" % size
+        f.write("TEST: %dM\n" % i)
+        try:
+            f.flush()
+            os.fsync(f)
+        except:
+            pass
+    f.write("PASS: memfill (%dM)\n" % size)
 
 
-def test_cpu():
+def test_cpu(args):
     """
     Stress the CPU
     """
@@ -50,6 +61,16 @@ def test_cpu():
             math.factorial(i)
 
 
+def test_devices(args):
+    if args:
+        if args[0] == "write":
+            test_devices_write()
+        else:
+            test_devices_read()
+    else:
+        test_devices_read()
+
+
 def test_devices_read():
     """
     Inf read from /dev/zero
@@ -90,27 +111,19 @@ def main():
     Main (infinite) loop.
     """
     if len(sys.argv) < 2:
-        print "FAIL: Incorrect usage"
+        print "FAIL: Incorrect usage (%s)" % sys.argv
         return -1
+    args = sys.argv[2:]
     if sys.argv[1] == "smoke":
-        test_smoke()
+        test_smoke(args)
     elif sys.argv[1] == "memfill":
-        if len(sys.argv) > 2:
-            test_memfill(int(sys.argv[2]))
-        else:
-            test_memfill()
+        test_memfill(args)
     elif sys.argv[1] == "cpu":
-        test_cpu()
+        test_cpu(args)
     elif sys.argv[1] == "devices":
-        if len(sys.argv) > 2:
-            if (sys.argv[2] == "write"):
-                test_devices_write()
-            else:
-                test_devices_read()
-        else:
-            test_devices_read()
+        test_devices(args)
     else:
-        print "FAIL: No test specified"
+        print "FAIL: No test specified (%s)" % sys.argv
 
 if __name__ == "__main__":
     main()
-- 
1.7.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/4] [NEW] cgroup test * general smoke_test + module dependend subtests (memory test included) * library for future use in other tests (kvm)
  2011-08-15 12:23 ` [PATCH 1/4] [NEW] cgroup test * general smoke_test + module dependend subtests (memory test included) * library for future use in other tests (kvm) Lukas Doktor
@ 2011-08-18 11:33   ` Jiri Zupka
  2011-08-21  9:15     ` Lukáš Doktor
  0 siblings, 1 reply; 8+ messages in thread
From: Jiri Zupka @ 2011-08-18 11:33 UTC (permalink / raw)
  To: Lukas Doktor; +Cc: kvm, root, autotest, kvm-autotest

Hi,
  some minor problem in some timeout. 
Commented down in code. 
Otherwise good work.

----- Original Message -----
> From: root <root@dhcp-26-193.brq.redhat.com>
> 
> cgroup.py:
> * structure for different cgroup subtests
> * contains basic "cgroup-memory" test
> 
> cgroup_common.py:
> * library for cgroup handling (intended to be used from kvm test in
> the future)
> * universal smoke_test for every module
> 
> cgroup_client.py:
> * application which is executed and controled using cgroups
> * contains smoke, memory, cpu and devices tests which were manually
> tested to break cgroup rules and will be used in the cgroup.py
> subtests
> 
> Signed-off-by: Lukas Doktor <ldoktor@redhat.com>
> ---
> client/tests/cgroup/cgroup.py | 239 +++++++++++++++++++++++++
> client/tests/cgroup/cgroup_client.py | 116 ++++++++++++
> client/tests/cgroup/cgroup_common.py | 327
> ++++++++++++++++++++++++++++++++++
> client/tests/cgroup/control | 12 ++
> 4 files changed, 694 insertions(+), 0 deletions(-)
> create mode 100755 client/tests/cgroup/cgroup.py
> create mode 100755 client/tests/cgroup/cgroup_client.py
> create mode 100755 client/tests/cgroup/cgroup_common.py
> create mode 100644 client/tests/cgroup/control
> 
> diff --git a/client/tests/cgroup/cgroup.py
> b/client/tests/cgroup/cgroup.py
> new file mode 100755
> index 0000000..112f012
> --- /dev/null
> +++ b/client/tests/cgroup/cgroup.py
> @@ -0,0 +1,239 @@
> +from autotest_lib.client.bin import test
> +from autotest_lib.client.common_lib import error
> +import os, logging
> +import time
> +from cgroup_common import Cgroup as CG
> +from cgroup_common import CgroupModules
> +
> +class cgroup(test.test):
> + """
> + Tests the cgroup functionalities
> + """
> + version = 1
> + _client = ""
> + modules = CgroupModules()
> +
> +
> + def run_once(self):
> + """
> + Try to access different resources which are restricted by cgroup.
> + """
> + logging.info('Start')
> +
> + err = ""
> + # Run available tests
> + for i in ['memory']:
> + try:
> + if self.modules.get_pwd(i):
> + if (eval ("self.test_%s()" % i)):
> + err += "%s, " % i
> + else:
> + logging.error("CGROUP: Skipping test_%s, module not "
> + "available/mounted", i)
> + err += "%s, " % i
> + except Exception, inst:
> + logging.error("CGROUP: test_%s fatal failure: %s", i, inst)
> + err += "%s, " % i
> +
> + if err:
> + raise error.TestFail('CGROUP: Some subtests failed (%s)' % err[:-2])
> +
> +
> + def setup(self):
> + """
> + Setup
> + """
> + logging.info('Setup')
> +
> + self._client = os.path.join(self.bindir, "cgroup_client.py")
> +
> + _modules = ['cpuset', 'ns', 'cpu', 'cpuacct', 'memory', 'devices',
> + 'freezer', 'net_cls', 'blkio']
> + if (self.modules.init(_modules) <= 0):
> + raise error.TestFail('Can\'t mount any cgroup modules')
> +
> +
> + def cleanup(self):
> + """
> + Unmount all cgroups and remove directories
> + """
> + logging.info('Cleanup')
> + self.modules.cleanup()
> +
> +
> + #############################
> + # TESTS
> + #############################
> + def test_memory(self):
> + """
> + Memory test
> + """
> + # Preparation
> + logging.info("Entering 'test_memory'")
> + item = CG('memory', self._client)
> + if item.initialize(self.modules):
> + logging.error("test_memory: cgroup init failed")
> + return -1
> +
> + if item.smoke_test():
> + logging.error("test_memory: smoke_test failed")
> + return -1
> +
> + pwd = item.mk_cgroup()
> + if pwd == None:
> + logging.error("test_memory: Can't create cgroup")
> + return -1
> +
> + logging.debug("test_memory: Memory filling test")
> +
> + f = open('/proc/meminfo','r')

Not clean way how to do this.. It is better to use regular expression.
But this is absolutely no important.

> + mem = f.readline()
> + while not mem.startswith("MemFree"):
> + mem = f.readline()

> + # Use only 1G or max of the free memory
> + mem = min(int(mem.split()[1])/1024, 1024)
> + mem = max(mem, 100) # at least 100M
> + if (item.get_property("memory.memsw.limit_in_bytes", supress=True)
> + != None):
> + memsw = True
> + # Clear swap
> + os.system("swapoff -a")
> + os.system("swapon -a")
> + f.seek(0)
> + swap = f.readline()
> + while not swap.startswith("SwapTotal"):
> + swap = f.readline()
> + swap = int(swap.split()[1])/1024
> + if swap < mem / 2:
> + logging.error("Not enough swap memory to test 'memsw'")
> + memsw = False
> + else:
> + # Doesn't support swap+memory limitation, disable swap
> + logging.info("'memsw' not supported")
> + os.system("swapoff -a")
> + memsw = False
> + logging.debug("test_memory: Initializition passed")
> +
> + ################################################
> + # Fill the memory without cgroup limitation
> + # Should pass
> + ################################################
> + logging.debug("test_memory: Memfill WO cgroup")
> + ps = item.test("memfill %d" % mem)
> + ps.stdin.write('\n')
> + i = 0
> + while ps.poll() == None:
> + if i > 60:
> + break
> + i += 1
> + time.sleep(1)
> + if i > 60:
> + logging.error("test_memory: Memory filling failed (WO cgroup)")
> + ps.terminate()
> + return -1
> + if not ps.stdout.readlines()[-1].startswith("PASS"):
> + logging.error("test_memory: Unsuccessful memory filling "
> + "(WO cgroup)")
> + return -1
> + logging.debug("test_memory: Memfill WO cgroup passed")
> +
> + ################################################
> + # Fill the memory with 1/2 memory limit
> + # memsw: should swap out part of the process and pass
> + # WO memsw: should fail (SIGKILL)
> + ################################################
> + logging.debug("test_memory: Memfill mem only limit")
> + ps = item.test("memfill %d" % mem)
> + if item.set_cgroup(ps.pid, pwd):
> + logging.error("test_memory: Could not set cgroup")
> + return -1
> + if item.set_property("memory.limit_in_bytes", (1024*1024*mem/2),
> pwd):
> + logging.error("test_memory: Could not set mem limit (mem)")
> + return -1
> + ps.stdin.write('\n')
> + i = 0
> + while ps.poll() == None:
> + if i > 60:
> + break
> + i += 1
> + time.sleep(1)
> + if i > 60:
> + logging.error("test_memory: Memory filling failed (mem)")
> + ps.terminate()
> + return -1
> + out = ps.stdout.readlines()
> + if len(out) < 2:
> + logging.error("test_memory: Process failed; output:\n%s", out)
> + return -1
> + if memsw:
> + if not out[-1].startswith("PASS"):
> + logging.error("test_memory: Unsuccessful memory filling (mem)")
> + logging.error("test_memory: cgroup_client.py returned %d; "
> + "output:\n%s", ps.poll(), out)
> + return -1
> + else:
> + if out[-1].startswith("PASS"):
> + logging.error("test_memory: Unexpected memory filling (mem)")
> + return -1
> + else:
> + filled = int(out[-2].split()[1][:-1])
> + if mem/2 > 1.5*filled:
> + logging.error("test_memory: Limit = %dM, Filled = %dM (+ "
> + "python overhead upto 1/3 (mem)", mem/2, filled)
> + else:
> + logging.debug("test_memory: Limit = %dM, Filled = %dM (+ "
> + "python overhead upto 1/3 (mem)", mem/2, filled)
> + logging.debug("test_memory: Memfill mem only cgroup passed")
> +
> + ################################################
> + # Fill the memory with 1/2 memory+swap limit
> + # Should fail
> + ################################################
> + logging.debug("test_memory: Memfill mem + swap limit")
> + if memsw:
> + ps = item.test("memfill %d" % mem)
> + if item.set_cgroup(ps.pid, pwd):
> + logging.error("test_memory: Could not set cgroup (memsw)")
> + return -1
> + if item.set_property("memory.memsw.limit_in_bytes",
> + (1024*1024*mem/2), pwd):
> + logging.error("test_memory: Could not set mem limit (memsw)")
> + return -1
> + ps.stdin.write('\n')
> + i = 0
> + while ps.poll() == None:
> + if i > 60:
> + break
> + i += 1
> + time.sleep(1)
> + if i > 60:
> + logging.error("test_memory: Memory filling failed (mem)")
> + ps.terminate()
> + return -1
> + out = ps.stdout.readlines()
> + if len(out) < 2:
> + logging.error("test_memory: Process failed; output:\n%s", out)
> + return -1
> + if out[-1].startswith("PASS"):
> + logging.error("test_memory: Unexpected memory filling (memsw)",
> + mem)
> + return -1
> + else:
> + filled = int(out[-2].split()[1][:-1])
> + if mem/2 > 1.5*filled:
> + logging.error("test_memory: Limit = %dM, Filled = %dM (+ "
> + "python overhead upto 1/3 (memsw)", mem/2, filled)
> + else:
> + logging.debug("test_memory: Limit = %dM, Filled = %dM (+ "
> + "python overhead upto 1/3 (memsw)", mem/2, filled)
> + logging.debug("test_memory: Memfill mem+swap cgroup passed")
> +
> + # cleanup
> + logging.debug("test_memory: Cleanup")
> + if item.rm_cgroup(pwd):
> + logging.error("test_memory: Can't remove cgroup directory")
> + return -1
> + os.system("swapon -a")
> +
> + logging.info("Leaving 'test_memory': PASSED")
> + return 0
> diff --git a/client/tests/cgroup/cgroup_client.py
> b/client/tests/cgroup/cgroup_client.py
> new file mode 100755
> index 0000000..ff098ef
> --- /dev/null
> +++ b/client/tests/cgroup/cgroup_client.py
> @@ -0,0 +1,116 @@
> +#!/usr/bin/python
> +# -*- coding: utf-8 -*-
> +"""
> +Interactive python script for testing cgroups
> +
> +@copyright: 2011 Red Hat Inc.
> +@author: Lukas Doktor <ldoktor@redhat.com>
> +"""
> +import array, sys, time, math
> +
> +def test_smoke():
> + """
> + SIGSTOP the process and after SIGCONT exits.
> + """
> + print "TEST: smoke"
> + print "TEST: wait for input"
> + raw_input()
> + print "PASS: smoke"
> +
> +
> +def test_memfill(size=1024):
> + """
> + SIGSTOP and after SIGCONT fills the memory up to size size.
> + """
> + print "TEST: memfill (%dM)" % size
> + print "TEST: wait for input"
> + raw_input()
> + mem = array.array('B')
> + buf = ""
> + for i in range(1024*1024):
> + buf += '\x00'
> + for i in range(size):
> + mem.fromstring(buf)
> + #for j in range(1024*1024):
> + # mem.append(0)
> + print "TEST: %dM" % i
> + print "PASS: memfill (%dM)" % size
> +
> +
> +def test_cpu():
> + """
> + Stress the CPU
> + """
> + print "TEST: cpu"
> + print "TEST: wait for input"
> + raw_input()
> + while True:
> + for i in range (1000, 10000):
> + math.factorial(i)
> +
> +
> +def test_devices_read():
> + """
> + Inf read from /dev/zero
> + """
> + print "TEST: devices read"
> + print "TEST: wait for input"
> + raw_input()
> +
> + dev = open("/dev/zero", 'r')
> + while True:
> + print "TEST: tick"
> + dev.flush()
> + dev.read(1024*1024)
> + time.sleep(1)
> +
> +
> +def test_devices_write():
> + """
> + Inf write into /dev/null device
> + """
> + print "TEST: devices write"
> + print "TEST: wait for input"
> + raw_input()
> +
> + dev = open("/dev/null", 'w')
> + buf = ""
> + for _ in range(1024*1024):
> + buf += '\x00'
> + while True:
> + print "TEST: tick"
> + dev.write(buf)
> + dev.flush()
> + time.sleep(1)
> +
> +
> +def main():
> + """
> + Main (infinite) loop.
> + """
> + if len(sys.argv) < 2:
> + print "FAIL: Incorrect usage"
> + return -1
> + if sys.argv[1] == "smoke":
> + test_smoke()
> + elif sys.argv[1] == "memfill":
> + if len(sys.argv) > 2:
> + test_memfill(int(sys.argv[2]))
> + else:
> + test_memfill()
> + elif sys.argv[1] == "cpu":
> + test_cpu()
> + elif sys.argv[1] == "devices":
> + if len(sys.argv) > 2:
> + if (sys.argv[2] == "write"):
> + test_devices_write()
> + else:
> + test_devices_read()
> + else:
> + test_devices_read()
> + else:
> + print "FAIL: No test specified"
> +
> +if __name__ == "__main__":
> + main()
> +
> diff --git a/client/tests/cgroup/cgroup_common.py
> b/client/tests/cgroup/cgroup_common.py
> new file mode 100755
> index 0000000..3fd1cf7
> --- /dev/null
> +++ b/client/tests/cgroup/cgroup_common.py
> @@ -0,0 +1,327 @@
> +#!/usr/bin/python
> +# -*- coding: utf-8 -*-
> +"""
> +Helpers for cgroup testing
> +
> +@copyright: 2011 Red Hat Inc.
> +@author: Lukas Doktor <ldoktor@redhat.com>
> +"""
> +import os, logging
> +import subprocess
> +from tempfile import mkdtemp
> +import time
> +
> +class Cgroup:
> + """
> + Cgroup handling class
> + """
> + def __init__(self, module, _client):
> + """
> + Constructor
> + @param module: Name of the cgroup module
> + @param _client: Test script pwd+name
> + """
> + self.module = module
> + self._client = _client
> + self.root = None
> +
> +
> + def initialize(self, modules):
> + """
> + Inicializes object for use
> + @param modules: array of all available cgroup modules
> + @return: 0 when PASSED
> + """
> + self.root = modules.get_pwd(self.module)
> + if self.root:
> + return 0
> + else:
> + logging.error("cg.initialize(): Module %s not found", self.module)
> + return -1
> + return 0
> +
> +
> + def mk_cgroup(self, root=None):
> + """
> + Creates new temporary cgroup
> + @param root: where to create this cgroup (default: self.root)
> + @return: 0 when PASSED
> + """
> + try:
> + if root:
> + pwd = mkdtemp(prefix='cgroup-', dir=root) + '/'
> + else:
> + pwd = mkdtemp(prefix='cgroup-', dir=self.root) + '/'
> + except Exception, inst:
> + logging.error("cg.mk_cgroup(): %s" , inst)
> + return None
> + return pwd
> +
> +
> + def rm_cgroup(self, pwd, supress=False):
> + """
> + Removes cgroup
> + @param pwd: cgroup directory
> + @param supress: supress output
> + @return: 0 when PASSED
> + """
> + try:
> + os.rmdir(pwd)
> + except Exception, inst:
> + if not supress:
> + logging.error("cg.rm_cgroup(): %s" , inst)
> + return -1
> + return 0
> +
> +
> + def test(self, cmd):
> + """
> + Executes cgroup_client.py with cmd parameter
> + @param cmd: command to be executed
> + @return: subprocess.Popen() process
> + """
> + logging.debug("cg.test(): executing paralel process '%s'" , cmd)
> + process = subprocess.Popen((self._client + ' ' + cmd), shell=True,
> + stdin=subprocess.PIPE, stdout=subprocess.PIPE,
> + stderr=subprocess.PIPE, close_fds=True)
> + return process
> +
> +
> + def is_cgroup(self, pid, pwd):
> + """
> + Checks if the 'pid' process is in 'pwd' cgroup
> + @param pid: pid of the process
> + @param pwd: cgroup directory
> + @return: 0 when is 'pwd' member
> + """
> + if open(pwd+'/tasks').readlines().count("%d\n" % pid) > 0:
> + return 0
> + else:
> + return -1
> +
> + def is_root_cgroup(self, pid):
> + """
> + Checks if the 'pid' process is in root cgroup (WO cgroup)
> + @param pid: pid of the process
> + @return: 0 when is 'root' member
> + """
> + return self.is_cgroup(pid, self.root)
> +
> + def set_cgroup(self, pid, pwd):
> + """
> + Sets cgroup membership
> + @param pid: pid of the process
> + @param pwd: cgroup directory
> + @return: 0 when PASSED
> + """
> + try:
> + open(pwd+'/tasks', 'w').write(str(pid))
> + except Exception, inst:
> + logging.error("cg.set_cgroup(): %s" , inst)
> + return -1
> + if self.is_cgroup(pid, pwd):
> + logging.error("cg.set_cgroup(): Setting %d pid into %s cgroup "
> + "failed", pid, pwd)
> + return -1
> + else:
> + return 0
> +
> + def set_root_cgroup(self, pid):
> + """
> + Resets the cgroup membership (sets to root)
> + @param pid: pid of the process
> + @return: 0 when PASSED
> + """
> + return self.set_cgroup(pid, self.root)
> +
> +
> + def get_property(self, prop, pwd=None, supress=False):
> + """
> + Gets the property value
> + @param prop: property name (file)
> + @param pwd: cgroup directory
> + @param supress: supress the output
> + @return: String value or None when FAILED
> + """
> + if pwd == None:
> + pwd = self.root
> + try:
> + ret = open(pwd+prop, 'r').readlines()
> + except Exception, inst:
> + ret = None
> + if not supress:
> + logging.error("cg.get_property(): %s" , inst)
> + return ret
> +
> +
> + def set_property(self, prop, value, pwd=None, check=True):
> + """
> + Sets the property value
> + @param prop: property name (file)
> + @param value: desired value
> + @param pwd: cgroup directory
> + @param check: check the value after setup
> + @return: 0 when PASSED
> + """
> + value = str(value)
> + if pwd == None:
> + pwd = self.root
> + try:
> + open(pwd+prop, 'w').write(value)
> + except Exception, inst:
> + logging.error("cg.set_property(): %s" , inst)
> + return -1
> + if check:
> + # Get the first line - '\n'
> + _value = self.get_property(prop, pwd)[0][:-1]
> + if value != _value:
> + logging.error("cg.set_property(): Setting failed: desired = %s,"
> + " real value = %s", value, _value)
> + return -1
> + return 0
> +
> +
> + def smoke_test(self):
> + """
> + Smoke test
> + Module independent basic tests
> + """
> + part = 0
> + pwd = self.mk_cgroup()
> + if pwd == None:
> + logging.error("cg.smoke_test[%d]: Can't create cgroup", part)
> + return -1
> +
> + part += 1
> + ps = self.test("smoke")
> + if ps == None:
> + logging.error("cg.smoke_test[%d]: Couldn't create process", part)
> + return -1
> +
> + part += 1
> + if (ps.poll() != None):
> + logging.error("cg.smoke_test[%d]: Process died unexpectidly", part)
> + return -1
> +
> + # New process should be a root member
> + part += 1
> + if self.is_root_cgroup(ps.pid):
> + logging.error("cg.smoke_test[%d]: Process is not a root member",
> + part)
> + return -1
> +
> + # Change the cgroup
> + part += 1
> + if self.set_cgroup(ps.pid, pwd):
> + logging.error("cg.smoke_test[%d]: Could not set cgroup", part)
> + return -1
> +
> + # Try to remove used cgroup
> + part += 1
> + if self.rm_cgroup(pwd, supress=True) == 0:
> + logging.error("cg.smoke_test[%d]: Unexpected successful deletion of"
> + " the used cgroup", part)
> + return -1
> +
> + # Return the process into the root cgroup
> + part += 1
> + if self.set_root_cgroup(ps.pid):
> + logging.error("cg.smoke_test[%d]: Could not return the root cgroup "
> + "membership", part)
> + return -1
> +
> + # It should be safe to remove the cgroup now
> + part += 1
> + if self.rm_cgroup(pwd):
> + logging.error("cg.smoke_test[%d]: Can't remove cgroup direcotry",
> + part)
> + return -1
> +
> + # Finish the process
> + part += 1
> + ps.stdin.write('\n')
> + time.sleep(2)

There should be bigger timeout. This is sometime make problem.
Process ends correct way but not in timeout.

> + if (ps.poll() == None):
> + logging.error("cg.smoke_test[%d]: Process is not finished", part)
> + return -1
> +
> + return 0
> +
> +
> +class CgroupModules:
> + """
> + Handles the list of different cgroup filesystems
> + """
> + def __init__(self):
> + self.modules = []
> + self.modules.append([])
> + self.modules.append([])
> + self.modules.append([])
> + self.mountdir = mkdtemp(prefix='cgroup-') + '/'
> +
> +
> + def init(self, _modules):
> + """
> + Checks the mounted modules and if necessarily mounts them into tmp
> + mountdir.
> + @param _modules: desired modules
> + @return: Number of initialized modules
> + """
> + mounts = []
> + fp = open('/proc/mounts', 'r')
> + line = fp.readline().split()
> + while line:
> + if line[2] == 'cgroup':
> + mounts.append(line)
> + line = fp.readline().split()
> + fp.close()
> +
> + for module in _modules:
> + # Is it already mounted?
> + i = False
> + for mount in mounts:
> + if mount[3].find(module) != -1:
> + self.modules[0].append(module)
> + self.modules[1].append(mount[1]+'/')
> + self.modules[2].append(False)
> + i = True
> + break
> +
> + if not i:
> + # Not yet mounted
> + os.mkdir(self.mountdir+module)
> + logging.info('mount -t cgroup -o %s %s %s', module, module,
> + self.mountdir+module)
> + if (os.system('mount -t cgroup -o %s %s %s'
> + % (module, module, self.mountdir+module)) == 0):
> + self.modules[0].append(module)
> + self.modules[1].append(self.mountdir+module)
> + self.modules[2].append(True)
> + else:
> + logging.error("Module '%s' is not available, mount failed",
> + module)
> + return len(self.modules[0])
> +
> +
> + def cleanup(self):
> + """
> + Unmount all cgroups and remove the mountdir
> + """
> + for i in range(len(self.modules[0])):
> + if self.modules[2][i]:
> + os.system('umount %s -l' % self.modules[1][i])
> + os.system('rm -rf %s' % self.mountdir)
> +
> +
> + def get_pwd(self, module):
> + """
> + Returns the mount directory of 'module'
> + @param module: desired module (memory, ...)
> + @return: mount directory of 'module' or None
> + """
> + try:
> + i = self.modules[0].index(module)
> + except Exception, inst:
> + logging.error("module %s not found: %s", module, inst)
> + return None
> + return self.modules[1][i]
> diff --git a/client/tests/cgroup/control b/client/tests/cgroup/control
> new file mode 100644
> index 0000000..86aec06
> --- /dev/null
> +++ b/client/tests/cgroup/control
> @@ -0,0 +1,12 @@
> +AUTHOR = "Lukas Doktor <ldoktor@redhat.com>"
> +NAME = "Cgroup"
> +TIME = "SHORT"
> +TEST_CATEGORY = "Functional"
> +TEST_CLASS = "General"
> +TEST_TYPE = "client"
> +
> +DOC = """
> +This test checks basic functionality of cgroups
> +"""
> +
> +job.run_test('cgroup')
> --
> 1.7.6

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/4] [NEW] cgroup test * general smoke_test + module dependend subtests (memory test included) * library for future use in other tests (kvm)
  2011-08-18 11:33   ` Jiri Zupka
@ 2011-08-21  9:15     ` Lukáš Doktor
  0 siblings, 0 replies; 8+ messages in thread
From: Lukáš Doktor @ 2011-08-21  9:15 UTC (permalink / raw)
  To: Jiri Zupka; +Cc: root, autotest, kvm, kvm-autotest, fyang, lmr

#SNIP

>> + pwd = item.mk_cgroup()
>> + if pwd == None:
>> + logging.error("test_memory: Can't create cgroup")
>> + return -1
>> +
>> + logging.debug("test_memory: Memory filling test")
>> +
>> + f = open('/proc/meminfo','r')
>
> Not clean way how to do this.. It is better to use regular expression.
> But this is absolutely no important.
>

OKi, anyway Ypu is trying to get get_mem_usage() function into utils. 
I'll use it then.
>> + mem = f.readline()
>> + while not mem.startswith("MemFree"):
>> + mem = f.readline()

#SNIP

>> + logging.error("cg.smoke_test[%d]: Can't remove cgroup direcotry",
>> + part)
>> + return -1
>> +
>> + # Finish the process
>> + part += 1
>> + ps.stdin.write('\n')
>> + time.sleep(2)
>
> There should be bigger timeout. This is sometime make problem.
> Process ends correct way but not in timeout.
>

OK, Lucas, can you please change it in patchset (if you intend to accept 
it?). 10 seconds seems to be more safe DL, thanks.

>> + if (ps.poll() == None):
>> + logging.error("cg.smoke_test[%d]: Process is not finished", part)
>> + return -1
>> +
>> + return 0
>> +
>> +

#SNIP

Thank you, Jiří.

kind regards,
Lukáš

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [autotest][PATCH] cgroup test + modifications
  2011-08-15 12:23 [autotest][PATCH] cgroup test + modifications Lukas Doktor
                   ` (3 preceding siblings ...)
  2011-08-15 12:23 ` [PATCH 4/4] [FIX] Use file instead of PIPE in memfill test (problem with sync) Lukas Doktor
@ 2011-09-01  8:03 ` Jan Stancek
  4 siblings, 0 replies; 8+ messages in thread
From: Jan Stancek @ 2011-09-01  8:03 UTC (permalink / raw)
  To: Lukas Doktor; +Cc: kvm, czhang, autotest, kvm-autotest

Hi Lukas,

I'm curious about motivation behind these tests, because 
if I'm not mistaken you are starting from scratch here.

Can you compare it to other cgroup tests out there?
Like the ones in ltp:
http://ltp.git.sourceforge.net/git/gitweb.cgi?p=ltp/ltp.git;a=tree;f=testcases/kernel/controllers;hb=HEAD

Regards,
Jan

----- Original Message -----
From: "Lukas Doktor" <ldoktor@redhat.com>
To: autotest@test.kernel.org, kvm@vger.kernel.org, kvm-autotest@redhat.com, fyang@redhat.com, lmr@redhat.com, ldoktor@redhat.com, jzupka@redhat.com
Sent: Monday, August 15, 2011 2:23:33 PM
Subject: [Autotest] [autotest][PATCH] cgroup test + modifications


Hi,

I changed a bit the structure and added the cpuset test.

The first patch is equal to previous post (including the missing file). Other pa
tches are bugfixies and new cpuset test.

Please let me know if this structure is usable so I can continue in test develop
ment.

Regards,
Lukáš
_______________________________________________
Autotest mailing list
Autotest@test.kernel.org
http://test.kernel.org/cgi-bin/mailman/listinfo/autotest
_______________________________________________
Autotest mailing list
Autotest@test.kernel.org
http://test.kernel.org/cgi-bin/mailman/listinfo/autotest

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-09-01  8:03 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-15 12:23 [autotest][PATCH] cgroup test + modifications Lukas Doktor
2011-08-15 12:23 ` [PATCH 1/4] [NEW] cgroup test * general smoke_test + module dependend subtests (memory test included) * library for future use in other tests (kvm) Lukas Doktor
2011-08-18 11:33   ` Jiri Zupka
2011-08-21  9:15     ` Lukáš Doktor
2011-08-15 12:23 ` [PATCH 2/4] bugfixies Lukas Doktor
2011-08-15 12:23 ` [PATCH 3/4] cpuset test Lukas Doktor
2011-08-15 12:23 ` [PATCH 4/4] [FIX] Use file instead of PIPE in memfill test (problem with sync) Lukas Doktor
2011-09-01  8:03 ` [autotest][PATCH] cgroup test + modifications Jan Stancek

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.