All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lukas Doktor <ldoktor@redhat.com>
To: autotest@test.kernel.org
Cc: kvm@vger.kernel.org, kvm-autotest@redhat.com
Subject: [PATCH] Adds cgroup handling library
Date: Mon,  8 Aug 2011 10:31:20 +0200	[thread overview]
Message-ID: <1312792280-19358-2-git-send-email-ldoktor@redhat.com> (raw)
In-Reply-To: <1312792280-19358-1-git-send-email-ldoktor@redhat.com>

[new] cgroup_common.py
* library for handling cgroups

Signed-off-by: Lukas Doktor <ldoktor@redhat.com>
---
 client/tests/cgroup/cgroup.py        |    5 +-
 client/tests/cgroup/cgroup_common.py |  327 ++++++++++++++++++++++++++++++++++
 2 files changed, 331 insertions(+), 1 deletions(-)
 create mode 100755 client/tests/cgroup/cgroup_common.py

diff --git a/client/tests/cgroup/cgroup.py b/client/tests/cgroup/cgroup.py
index d043d65..112f012 100755
--- a/client/tests/cgroup/cgroup.py
+++ b/client/tests/cgroup/cgroup.py
@@ -118,6 +118,7 @@ class cgroup(test.test):
         # 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
@@ -141,6 +142,7 @@ class cgroup(test.test):
         # 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")
@@ -187,6 +189,7 @@ class cgroup(test.test):
         # 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):
@@ -226,11 +229,11 @@ class cgroup(test.test):
             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.debug("test_memory: Cleanup passed")
 
         logging.info("Leaving 'test_memory': PASSED")
         return 0
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]
-- 
1.7.6

  reply	other threads:[~2011-08-08  8:31 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-08-02 14:50 [autotest][PATCH] Add cgroup test Lukas Doktor
2011-08-02 14:50 ` [PATCH] [NEW] cgroup test * general smoke_test + module dependend subtests (memory test included) * library for future use in other tests (kvm) Lukas Doktor
2011-08-03 23:57   ` [Autotest] " Lucas Meneghel Rodrigues
2011-08-08  6:49   ` Jiri Zupka
2011-08-08  8:31 ` Missing cgroup_common.py Lukas Doktor
2011-08-08  8:31   ` Lukas Doktor [this message]
2011-08-09 10:57     ` [PATCH] Adds cgroup handling library Jiri Zupka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1312792280-19358-2-git-send-email-ldoktor@redhat.com \
    --to=ldoktor@redhat.com \
    --cc=autotest@test.kernel.org \
    --cc=kvm-autotest@redhat.com \
    --cc=kvm@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.