[PATCH 2/4] [autotest] cgroup: cleanup and structural changes

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

 



 * Use exceptions instead of returns
 * cgroup and cgroup-kvm tests were modified to fit
 * other code cleanups

Signed-off-by: Lukas Doktor <ldoktor@xxxxxxxxxx>
---
 client/tests/cgroup/cgroup.py        |  169 +++++++++++++++++-----------------
 client/tests/cgroup/cgroup_common.py |  140 ++++++++++------------------
 client/tests/kvm/tests/cgroup.py     |   14 +--
 3 files changed, 138 insertions(+), 185 deletions(-)

diff --git a/client/tests/cgroup/cgroup.py b/client/tests/cgroup/cgroup.py
index 171f43e..8626c52 100644
--- a/client/tests/cgroup/cgroup.py
+++ b/client/tests/cgroup/cgroup.py
@@ -1,4 +1,12 @@
-import os, logging
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""
+Autotest test for testing cgroup functionalities
+
+@copyright: 2011 Red Hat Inc.
+@author: Lukas Doktor <ldoktor@xxxxxxxxxx>
+"""
+import os, sys, logging
 import time
 from tempfile import NamedTemporaryFile
 
@@ -6,6 +14,7 @@ from autotest_lib.client.bin import test, utils
 from autotest_lib.client.common_lib import error
 from cgroup_common import Cgroup as CG
 from cgroup_common import CgroupModules
+from cgroup_common import _traceback
 
 class cgroup(test.test):
     """
@@ -15,7 +24,7 @@ class cgroup(test.test):
     """
     version = 1
     _client = ""
-    modules = CgroupModules()
+    modules = None
 
     def run_once(self):
         """
@@ -25,25 +34,26 @@ class cgroup(test.test):
 
         err = ""
         # Run available tests
-        for i in ['memory', 'cpuset']:
-            logging.info("---< 'test_%s' START >---", i)
+        for subtest in ['memory', 'cpuset']:
+            logging.info("---< 'test_%s' START >---", subtest)
             try:
-                if not self.modules.get_pwd(i):
+                if not self.modules.get_pwd(subtest):
                     raise error.TestFail("module not available/mounted")
-                t_function = getattr(self, "test_%s" % i)
+                t_function = getattr(self, "test_%s" % subtest)
                 t_function()
-                logging.info("---< 'test_%s' PASSED >---", i)
+                logging.info("---< 'test_%s' PASSED >---", subtest)
             except AttributeError:
-                err += "%s, " % i
-                logging.error("test_%s: Test doesn't exist", i)
-                logging.info("---< 'test_%s' FAILED >---", i)
-            except Exception, inst:
-                err += "%s, " % i
-                logging.error("test_%s: %s", i, inst)
-                logging.info("---< 'test_%s' FAILED >---", i)
+                err += "%s, " % subtest
+                logging.error("test_%s: Test doesn't exist", subtest)
+                logging.info("---< 'test_%s' FAILED >---", subtest)
+            except Exception:
+                err += "%s, " % subtest
+                tb = _traceback("test_%s" % subtest, sys.exc_info())
+                logging.error("test_%s: FAILED%s", subtest, tb)
+                logging.info("---< 'test_%s' FAILED >---", subtest)
 
         if err:
-            logging.error('Some subtests failed (%s)' % err[:-2])
+            logging.error('Some subtests failed (%s)', err[:-2])
             raise error.TestFail('Some subtests failed (%s)' % err[:-2])
 
 
@@ -57,16 +67,16 @@ class cgroup(test.test):
 
         _modules = ['cpuset', 'ns', 'cpu', 'cpuacct', 'memory', 'devices',
                     'freezer', 'net_cls', 'blkio']
+        self.modules = CgroupModules()
         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()
+        """ Cleanup """
+        logging.debug('cgroup_test cleanup')
+        print "Cleanup"
+        del (self.modules)
 
 
     #############################
@@ -77,7 +87,7 @@ class cgroup(test.test):
         Memory test
         """
         def cleanup(supress=False):
-            # cleanup
+            """ cleanup """
             logging.debug("test_memory: Cleanup")
             err = ""
             if item.rm_cgroup(pwd):
@@ -87,51 +97,46 @@ class cgroup(test.test):
 
             if err:
                 if supress:
-                    logging.warn("Some parts of cleanup failed%s" % err)
+                    logging.warn("Some parts of cleanup failed%s", err)
                 else:
                     raise error.TestFail("Some parts of cleanup failed%s" % err)
 
         # Preparation
         item = CG('memory', self._client)
-        if item.initialize(self.modules):
-            raise error.TestFail("cgroup init failed")
-
-        if item.smoke_test():
-            raise error.TestFail("smoke_test failed")
-
+        item.initialize(self.modules)
+        item.smoke_test()
         pwd = item.mk_cgroup()
-        if pwd == None:
-            raise error.TestFail("Can't create cgroup")
 
         logging.debug("test_memory: Memory filling test")
-
-        f = open('/proc/meminfo','r')
-        mem = f.readline()
+        meminfo = open('/proc/meminfo','r')
+        mem = meminfo.readline()
         while not mem.startswith("MemFree"):
-            mem = f.readline()
+            mem = meminfo.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
-        memsw_limit_bytes = item.get_property("memory.memsw.limit_in_bytes",
-                                              supress=True)
-        if memsw_limit_bytes is not None:
+        try:
+            memsw_limit_bytes = item.get_property("memory.memsw.limit_in_bytes")
+        except error.TestFail:
+            # Doesn't support memsw limitation -> disabling
+            logging.info("System does not support 'memsw'")
+            utils.system("swapoff -a")
+            memsw = False
+        else:
+            # Supports memsw
             memsw = True
             # Clear swap
             utils.system("swapoff -a")
             utils.system("swapon -a")
-            f.seek(0)
-            swap = f.readline()
+            meminfo.seek(0)
+            swap = meminfo.readline()
             while not swap.startswith("SwapTotal"):
-                swap = f.readline()
+                swap = meminfo.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("System does not support 'memsw'")
-            utils.system("swapoff -a")
-            memsw = False
+        meminfo.close()
         outf = NamedTemporaryFile('w+', prefix="cgroup_client-",
                                   dir="/tmp")
         logging.debug("test_memory: Initializition passed")
@@ -170,10 +175,8 @@ class cgroup(test.test):
         ################################################
         logging.debug("test_memory: Memfill mem only limit")
         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):
-            raise error.TestFail("Could not set mem limit (mem)")
+        item.set_cgroup(ps.pid, pwd)
+        item.set_prop("memory.limit_in_bytes", ("%dM" % (mem/2)), pwd)
         ps.stdin.write('\n')
         i = 0
         while ps.poll() == None:
@@ -218,10 +221,8 @@ class cgroup(test.test):
         if memsw:
             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):
-                raise error.TestFail("Could not set mem limit (memsw)")
+            item.set_cgroup(ps.pid, pwd)
+            item.set_prop("memory.memsw.limit_in_bytes", "%dM"%(mem/2), pwd)
             ps.stdin.write('\n')
             i = 0
             while ps.poll() == None:
@@ -265,9 +266,9 @@ class cgroup(test.test):
         Cpuset test
         1) Initiate CPU load on CPU0, than spread into CPU* - CPU0
         """
-        class per_cpu_load:
+        class LoadPerCpu:
             """
-            Handles the per_cpu_load stats
+            Handles the LoadPerCpu stats
             self.values [cpus, cpu0, cpu1, ...]
             """
             def __init__(self):
@@ -275,14 +276,14 @@ class cgroup(test.test):
                 Init
                 """
                 self.values = []
-                self.f = open('/proc/stat', 'r')
-                line = self.f.readline()
+                self.stat = open('/proc/stat', 'r')
+                line = self.stat.readline()
                 while line:
                     if line.startswith('cpu'):
                         self.values.append(int(line.split()[1]))
                     else:
                         break
-                    line = self.f.readline()
+                    line = self.stat.readline()
 
             def reload(self):
                 """
@@ -295,11 +296,11 @@ class cgroup(test.test):
                 Get the current values
                 @return vals: array of current values [cpus, cpu0, cpu1..]
                 """
-                self.f.seek(0)
-                self.f.flush()
+                self.stat.seek(0)
+                self.stat.flush()
                 vals = []
-                for i in range(len(self.values)):
-                    vals.append(int(self.f.readline().split()[1]))
+                for _ in range(len(self.values)):
+                    vals.append(int(self.stat.readline().split()[1]))
                 return vals
 
             def tick(self):
@@ -316,11 +317,12 @@ class cgroup(test.test):
                 return ret
 
         def cleanup(supress=False):
-            # cleanup
+            """ cleanup """
             logging.debug("test_cpuset: Cleanup")
             err = ""
             try:
                 for task in tasks:
+                    i = 0
                     for i in range(10):
                         task.terminate()
                         if task.poll() != None:
@@ -334,7 +336,7 @@ class cgroup(test.test):
                 err += "\nCan't remove cgroup direcotry"
             if err:
                 if supress:
-                    logging.warn("Some parts of cleanup failed%s" % err)
+                    logging.warn("Some parts of cleanup failed%s", err)
                 else:
                     raise error.TestFail("Some parts of cleanup failed%s" % err)
 
@@ -343,8 +345,8 @@ class cgroup(test.test):
         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
+        # in cpuset cgroup it's necessarily to set certain values before
+        # usage. Thus smoke_test will fail.
         #if item.smoke_test():
         #    raise error.TestFail("smoke_test failed")
 
@@ -355,9 +357,6 @@ class cgroup(test.test):
             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)
@@ -378,25 +377,27 @@ class cgroup(test.test):
         # 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):
+            try:
+                item.set_cgroup(tasks[i].pid, pwd)
+            except error.TestFail, inst:
                 cleanup(True)
-                raise error.TestFail("Failed to set cgroup")
+                raise error.TestFail("Failed to set cgroup: %s", inst)
             tasks[i].stdin.write('\n')
-        stats = per_cpu_load()
+        stats = LoadPerCpu()
         # 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:
+        stat1 = stats.tick()[1:]
+        stat2 = stat1[1:]
+        stat1 = stat1[0]
+        for _stat in stat2:
+            if stat1 < _stat:
                 cleanup(True)
                 raise error.TestFail("Unused processor had higher utilization\n"
                                      "used cpu: %s, remaining cpus: %s"
-                                     % (s1, s2))
+                                     % (stat1, stat2))
 
         if no_cpus == 2:
             item.set_property("cpuset.cpus", "1", pwd)
@@ -404,15 +405,15 @@ class cgroup(test.test):
             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:
+        stat1 = stats.tick()[1:]
+        stat2 = stat1[0]
+        stat1 = stat1[1:]
+        for _stat in stat1:
+            if stat2 > _stat:
                 cleanup(True)
                 raise error.TestFail("Unused processor had higher utilization\n"
                                      "used cpus: %s, remaining cpu: %s"
-                                     % (s1, s2))
+                                     % (stat1, stat2))
         logging.debug("test_cpuset: Cpu allocation test passed")
 
         ################################################
diff --git a/client/tests/cgroup/cgroup_common.py b/client/tests/cgroup/cgroup_common.py
index 6934926..7a514c6 100755
--- a/client/tests/cgroup/cgroup_common.py
+++ b/client/tests/cgroup/cgroup_common.py
@@ -6,11 +6,24 @@ Helpers for cgroup testing.
 @copyright: 2011 Red Hat Inc.
 @author: Lukas Doktor <ldoktor@xxxxxxxxxx>
 """
-import os, logging, subprocess, time, shutil
+import logging, os, shutil, subprocess, time, traceback
 from tempfile import mkdtemp
 from autotest_lib.client.bin import utils
 from autotest_lib.client.common_lib import error
 
+def _traceback(name, exc_info):
+    """
+    Formats traceback into lines "name: line\nname: line"
+    @param name: desired line preposition
+    @param exc_info: sys.exc_info of the exception
+    @return: string which contains beautifully formatted exception
+    """
+    out = "\n"
+    for line in traceback.format_exception(exc_info[0], exc_info[1],
+                                           exc_info[2]):
+        out += "%s: %s" % (name, line)
+    return out
+
 
 class Cgroup(object):
     """
@@ -44,15 +57,11 @@ class Cgroup(object):
         Initializes 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
+        if not self.root:
+            raise error.TestFail("cg.initialize(): Module %s not found"
+                                                                % self.module)
 
 
     def mk_cgroup(self, root=None):
@@ -67,19 +76,16 @@ class Cgroup(object):
             else:
                 pwd = mkdtemp(prefix='cgroup-', dir=self.root) + '/'
         except Exception, inst:
-            logging.error("cg.mk_cgroup(): %s" , inst)
-            return None
+            raise error.TestFail("cg.mk_cgroup(): %s" % inst)
         self.cgroups.append(pwd)
         return pwd
 
 
-    def rm_cgroup(self, pwd, supress=False):
+    def rm_cgroup(self, pwd):
         """
         Removes cgroup.
 
         @param pwd: cgroup directory.
-        @param supress: supress output.
-        @return: 0 when PASSED
         """
         try:
             os.rmdir(pwd)
@@ -88,10 +94,7 @@ class Cgroup(object):
             logging.warn("cg.rm_cgroup(): Removed cgroup which wasn't created"
                          "using this Cgroup")
         except Exception, inst:
-            if not supress:
-                logging.error("cg.rm_cgroup(): %s" , inst)
-            return -1
-        return 0
+            raise error.TestFail("cg.rm_cgroup(): %s" % inst)
 
 
     def test(self, cmd):
@@ -136,19 +139,14 @@ class Cgroup(object):
         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
+            raise error.TestFail("cg.set_cgroup(): %s" % inst)
         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
+            raise error.TestFail("cg.set_cgroup(): Setting %d pid into %s "
+                                 "cgroup failed" % (pid, pwd))
 
     def set_root_cgroup(self, pid):
         """
@@ -159,29 +157,25 @@ class Cgroup(object):
         return self.set_cgroup(pid, self.root)
 
 
-    def get_prop(self, prop, pwd=None, supress=False):
+    def get_prop(self, prop, pwd=None):
         """
         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)
+        tmp = self.get_property(prop, pwd)
         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):
+    def get_property(self, prop, pwd=None):
         """
         Gets the property value
         @param prop: property name (file)
         @param pwd: cgroup directory
-        @param supress: supress the output
         @return: [] values or None when FAILED
         """
         if pwd == None:
@@ -189,10 +183,9 @@ class Cgroup(object):
         try:
             ret = open(pwd+prop, 'r').readlines()
         except Exception, inst:
-            ret = None
-            if not supress:
-                logging.error("cg.get_property(): %s" , inst)
-        return ret
+            raise error.TestFail("cg.get_property(): %s" % inst)
+        else:
+            return ret
 
 
     def set_prop(self, prop, value, pwd=None, check=True):
@@ -202,7 +195,6 @@ class Cgroup(object):
         @param value: desired value
         @param pwd: cgroup directory
         @param check: check the value after setup
-        @return: 0 when PASSED
         """
         _value = value
         try:
@@ -216,9 +208,9 @@ class Cgroup(object):
             elif value[-1] == 'G':
                 value = int(value[:-1]) * 1073741824
         except:
-            logging.error("cg.set_prop() fallback into cg.set_property.")
+            logging.warn("cg.set_prop() fallback into cg.set_property.")
             value = _value
-        return self.set_property(prop, value, pwd, check)
+        self.set_property(prop, value, pwd, check)
 
 
     def set_property(self, prop, value, pwd=None, check=True):
@@ -228,7 +220,6 @@ class Cgroup(object):
         @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:
@@ -236,16 +227,14 @@ class Cgroup(object):
         try:
             open(pwd+prop, 'w').write(value)
         except Exception, inst:
-            logging.error("cg.set_property(): %s" , inst)
-            return -1
+            raise error.TestFail("cg.set_property(): %s" % inst)
         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
+                raise error.TestFail("cg.set_property(): Setting failed: "
+                                     "desired = %s, real value = %s"
+                                     % (value, _value))
 
 
     def smoke_test(self):
@@ -253,66 +242,42 @@ class Cgroup(object):
         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
+            raise error.TestFail("cg.smoke_test: Couldn't create process")
 
-        part += 1
         if (ps.poll() != None):
-            logging.error("cg.smoke_test[%d]: Process died unexpectidly", part)
-            return -1
+            raise error.TestFail("cg.smoke_test: Process died unexpectidly")
 
         # 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
+            raise error.TestFail("cg.smoke_test: Process is not a root member")
 
         # 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
+        self.set_cgroup(ps.pid, pwd)
 
         # 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
+        try:
+            self.rm_cgroup(pwd)
+        except error.TestFail:
+            pass
+        else:
+            raise error.TestFail("cg.smoke_test: Unexpected successful deletion"
+                                 " of the used cgroup")
 
         # 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
+        self.set_root_cgroup(ps.pid)
 
         # 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 directory",
-                          part)
-            return -1
+        self.rm_cgroup(pwd)
 
         # 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
+            raise error.TestFail("cg.smoke_test: Process is not finished")
 
 
 class CgroupModules(object):
@@ -386,13 +351,6 @@ class CgroupModules(object):
         return len(self.modules[0])
 
 
-    def cleanup(self):
-        """
-        Kept for compatibility
-        """
-        pass
-
-
     def get_pwd(self, module):
         """
         Returns the mount directory of 'module'
diff --git a/client/tests/kvm/tests/cgroup.py b/client/tests/kvm/tests/cgroup.py
index d6418b5..415b334 100644
--- a/client/tests/kvm/tests/cgroup.py
+++ b/client/tests/kvm/tests/cgroup.py
@@ -185,18 +185,12 @@ def run_cgroup(test, params, env):
                 raise error.TestError("Could not initialize blkio Cgroup")
             for i in range(2):
                 pwd.append(blkio.mk_cgroup())
-                if pwd[i] == None:
-                    raise error.TestError("Can't create cgroup")
-                if blkio.set_cgroup(self.vms[i].get_shell_pid(), pwd[i]):
-                    raise error.TestError("Could not set cgroup")
+                blkio.set_cgroup(self.vms[i].get_shell_pid(), pwd[i])
                 # Move all existing threads into cgroup
                 for tmp in get_all_pids(self.vms[i].get_shell_pid()):
-                    if blkio.set_cgroup(int(tmp), pwd[i]):
-                        raise error.TestError("Could not set cgroup")
-            if self.blkio.set_property("blkio.weight", 100, pwd[0]):
-                raise error.TestError("Could not set blkio.weight")
-            if self.blkio.set_property("blkio.weight", 1000, pwd[1]):
-                raise error.TestError("Could not set blkio.weight")
+                    blkio.set_cgroup(int(tmp), pwd[i])
+            self.blkio.set_property("blkio.weight", 100, pwd[0])
+            self.blkio.set_property("blkio.weight", 1000, pwd[1])
 
             # Add dummy drives
             # TODO: implement also using QMP.
-- 
1.7.6.2

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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