* [kvm-autotest] cgroup-kvm: Four new BlkioThrottle tests
@ 2011-10-07 18:24 Lukas Doktor
2011-10-07 18:24 ` [PATCH 1/4] [kvm-autotest] cgroup-kvm: add_*_drive / rm_drive Lukas Doktor
` (5 more replies)
0 siblings, 6 replies; 10+ messages in thread
From: Lukas Doktor @ 2011-10-07 18:24 UTC (permalink / raw)
To: autotest, kvm, kvm-autotest, akong, lmr, ldoktor, jzupka
This is a patchset with four new tests to KVM specific cgroup testing. Also I made some modifications into (general) cgroup_common library which makes cgroup testing better readable and more safe to execute. Please find the details in each patch.
Also please beware of qemu-kvm bugs which occurred for me (qemu-kvm 0.15.0 F17) which led to qemu SEGFAULTS or even to dysfunction (qemu-kvm 0.14 F15). I'll fill in Bugzilla on Monday.
This was also sent as a github pull request, so if you feel like commenting on the pull request, be my guest:
https://github.com/autotest/autotest/pull/33
Best regards,
Lukáš
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/4] [kvm-autotest] cgroup-kvm: add_*_drive / rm_drive
2011-10-07 18:24 [kvm-autotest] cgroup-kvm: Four new BlkioThrottle tests Lukas Doktor
@ 2011-10-07 18:24 ` Lukas Doktor
2011-10-10 10:26 ` Jiri Zupka
2011-10-07 18:24 ` [PATCH 2/4] [autotest] cgroup: cleanup and structural changes Lukas Doktor
` (4 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Lukas Doktor @ 2011-10-07 18:24 UTC (permalink / raw)
To: autotest, kvm, kvm-autotest, akong, lmr, ldoktor, jzupka
* functions for adding and removal of drive to vm using host-file or
host-scsi_debug device.
Signed-off-by: Lukas Doktor <ldoktor@redhat.com>
---
client/tests/kvm/tests/cgroup.py | 125 ++++++++++++++++++++++++++++++++-----
1 files changed, 108 insertions(+), 17 deletions(-)
diff --git a/client/tests/kvm/tests/cgroup.py b/client/tests/kvm/tests/cgroup.py
index b9a10ea..d6418b5 100644
--- a/client/tests/kvm/tests/cgroup.py
+++ b/client/tests/kvm/tests/cgroup.py
@@ -17,6 +17,108 @@ def run_cgroup(test, params, env):
vms = None
tests = None
+ # Func
+ def get_device_driver():
+ """
+ Discovers the used block device driver {ide, scsi, virtio_blk}
+ @return: Used block device driver {ide, scsi, virtio}
+ """
+ if test.tagged_testname.count('virtio_blk'):
+ return "virtio"
+ elif test.tagged_testname.count('scsi'):
+ return "scsi"
+ else:
+ return "ide"
+
+
+ def add_file_drive(vm, driver=get_device_driver(), host_file=None):
+ """
+ Hot-add a drive based on file to a vm
+ @param vm: Desired VM
+ @param driver: which driver should be used (default: same as in test)
+ @param host_file: Which file on host is the image (default: create new)
+ @return: Tupple(ret_file, device)
+ ret_file: created file handler (None if not created)
+ device: PCI id of the virtual disk
+ """
+ if not host_file:
+ host_file = tempfile.NamedTemporaryFile(prefix="cgroup-disk-",
+ suffix=".iso")
+ utils.system("dd if=/dev/zero of=%s bs=1M count=8 &>/dev/null"
+ % (host_file.name))
+ ret_file = host_file
+ else:
+ ret_file = None
+
+ out = vm.monitor.cmd("pci_add auto storage file=%s,if=%s,snapshot=off,"
+ "cache=off" % (host_file.name, driver))
+ dev = re.search(r'OK domain (\d+), bus (\d+), slot (\d+), function \d+',
+ out)
+ if not dev:
+ raise error.TestFail("Can't add device(%s, %s, %s): %s" % (vm,
+ host_file.name, driver, out))
+ device = "%s:%s:%s" % dev.groups()
+ return (ret_file, device)
+
+
+ def add_scsi_drive(vm, driver=get_device_driver(), host_file=None):
+ """
+ Hot-add a drive based on scsi_debug device to a vm
+ @param vm: Desired VM
+ @param driver: which driver should be used (default: same as in test)
+ @param host_file: Which dev on host is the image (default: create new)
+ @return: Tupple(ret_file, device)
+ ret_file: string of the created dev (None if not created)
+ device: PCI id of the virtual disk
+ """
+ if not host_file:
+ if utils.system_output("lsmod | grep scsi_debug -c") == 0:
+ utils.system("modprobe scsi_debug dev_size_mb=8 add_host=0")
+ utils.system("echo 1 > /sys/bus/pseudo/drivers/scsi_debug/add_host")
+ host_file = utils.system_output("ls /dev/sd* | tail -n 1")
+ # Enable idling in scsi_debug drive
+ utils.system("echo 1 > /sys/block/%s/queue/rotational" % host_file)
+ ret_file = host_file
+ else:
+ # Don't remove this device during cleanup
+ # Reenable idling in scsi_debug drive (in case it's not)
+ utils.system("echo 1 > /sys/block/%s/queue/rotational" % host_file)
+ ret_file = None
+
+ out = vm.monitor.cmd("pci_add auto storage file=%s,if=%s,snapshot=off,"
+ "cache=off" % (host_file, driver))
+ dev = re.search(r'OK domain (\d+), bus (\d+), slot (\d+), function \d+',
+ out)
+ if not dev:
+ raise error.TestFail("Can't add device(%s, %s, %s): %s" % (vm,
+ host_file, driver, out))
+ device = "%s:%s:%s" % dev.groups()
+ return (ret_file, device)
+
+
+ def rm_drive(vm, host_file, device):
+ """
+ Remove drive from vm and device on disk
+ ! beware to remove scsi devices in reverse order !
+ """
+ vm.monitor.cmd("pci_del %s" % device)
+
+ if isinstance(host_file, file): # file
+ host_file.close()
+ elif isinstance(host_file, str): # scsi device
+ utils.system("echo -1> /sys/bus/pseudo/drivers/scsi_debug/add_host")
+ else: # custom file, do nothing
+ pass
+
+ def get_all_pids(ppid):
+ """
+ Get all PIDs of children/threads of parent ppid
+ param ppid: parent PID
+ return: list of PIDs of all children/threads of ppid
+ """
+ return (utils.system_output("ps -L --ppid=%d -o lwp" % ppid)
+ .split('\n')[1:])
+
# Tests
class _TestBlkioBandwidth:
"""
@@ -46,9 +148,8 @@ def run_cgroup(test, params, env):
"""
err = ""
try:
- for i in range (2):
- vms[i].monitor.cmd("pci_del %s" % self.devices[i])
- self.files[i].close()
+ for i in range(1, -1, -1):
+ rm_drive(vms[i], self.files[i], self.devices[i])
except Exception, failure_detail:
err += "\nCan't remove PCI drive: %s" % failure_detail
try:
@@ -89,8 +190,7 @@ def run_cgroup(test, params, env):
if blkio.set_cgroup(self.vms[i].get_shell_pid(), pwd[i]):
raise error.TestError("Could not set cgroup")
# Move all existing threads into cgroup
- for tmp in utils.system_output("ps -L --ppid=%d -o lwp"
- % self.vms[i].get_shell_pid()).split('\n')[1:]:
+ 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]):
@@ -101,18 +201,9 @@ def run_cgroup(test, params, env):
# Add dummy drives
# TODO: implement also using QMP.
for i in range(2):
- self.files.append(tempfile.NamedTemporaryFile(
- prefix="cgroup-disk-",
- suffix=".iso"))
- utils.system("dd if=/dev/zero of=%s bs=1M count=10 &>/dev/null"
- % (self.files[i].name))
- out = vms[i].monitor.cmd("pci_add auto storage file=%s,"
- "if=virtio,snapshot=off,cache=off"
- % (self.files[i].name))
- out = re.search(r'OK domain (\d+), bus (\d+), slot (\d+), '
- 'function \d+', out).groups()
- self.devices.append("%s:%s:%s" % out)
-
+ (host_file, device) = add_file_drive(vms[i], "virtio")
+ self.files.append(host_file)
+ self.devices.append(device)
def run(self):
"""
--
1.7.6.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/4] [autotest] cgroup: cleanup and structural changes
2011-10-07 18:24 [kvm-autotest] cgroup-kvm: Four new BlkioThrottle tests Lukas Doktor
2011-10-07 18:24 ` [PATCH 1/4] [kvm-autotest] cgroup-kvm: add_*_drive / rm_drive Lukas Doktor
@ 2011-10-07 18:24 ` Lukas Doktor
2011-10-07 18:24 ` [PATCH 3/4] [autotest] cgroup: {set,get}_property functions unification, bugfixies Lukas Doktor
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Lukas Doktor @ 2011-10-07 18:24 UTC (permalink / raw)
To: autotest, kvm, kvm-autotest, akong, lmr, ldoktor, jzupka
* Use exceptions instead of returns
* cgroup and cgroup-kvm tests were modified to fit
* other code cleanups
Signed-off-by: Lukas Doktor <ldoktor@redhat.com>
---
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@redhat.com>
+"""
+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@redhat.com>
"""
-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
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/4] [autotest] cgroup: {set,get}_property functions unification, bugfixies
2011-10-07 18:24 [kvm-autotest] cgroup-kvm: Four new BlkioThrottle tests Lukas Doktor
2011-10-07 18:24 ` [PATCH 1/4] [kvm-autotest] cgroup-kvm: add_*_drive / rm_drive Lukas Doktor
2011-10-07 18:24 ` [PATCH 2/4] [autotest] cgroup: cleanup and structural changes Lukas Doktor
@ 2011-10-07 18:24 ` Lukas Doktor
2011-10-07 18:24 ` [PATCH 4/4] [kvm-autotest] cgroup-kvm: New subtest: TestBlkioThrottle* Lukas Doktor
` (2 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Lukas Doktor @ 2011-10-07 18:24 UTC (permalink / raw)
To: autotest, kvm, kvm-autotest, akong, lmr, ldoktor, jzupka
* override "check" parameter to True / False / String (different value)
* add checkprop parameter to change the property which is used to check the
value.
* use more sane "set_property_h" function name instead of "set_prop"
* change raise error.TestFail for error.TestError
* get_property: return [""] when no input
* code cleanup
Signed-off-by: Lukas Doktor <ldoktor@redhat.com>
---
client/tests/cgroup/cgroup.py | 10 ++--
client/tests/cgroup/cgroup_common.py | 102 ++++++++++++++++------------------
2 files changed, 53 insertions(+), 59 deletions(-)
diff --git a/client/tests/cgroup/cgroup.py b/client/tests/cgroup/cgroup.py
index 8626c52..a290d76 100644
--- a/client/tests/cgroup/cgroup.py
+++ b/client/tests/cgroup/cgroup.py
@@ -176,7 +176,7 @@ class cgroup(test.test):
logging.debug("test_memory: Memfill mem only limit")
ps = item.test("memfill %d %s" % (mem, outf.name))
item.set_cgroup(ps.pid, pwd)
- item.set_prop("memory.limit_in_bytes", ("%dM" % (mem/2)), pwd)
+ item.set_property_h("memory.limit_in_bytes", ("%dM" % (mem/2)), pwd)
ps.stdin.write('\n')
i = 0
while ps.poll() == None:
@@ -222,7 +222,7 @@ class cgroup(test.test):
logging.debug("test_memory: Memfill mem + swap limit")
ps = item.test("memfill %d %s" % (mem, outf.name))
item.set_cgroup(ps.pid, pwd)
- item.set_prop("memory.memsw.limit_in_bytes", "%dM"%(mem/2), pwd)
+ item.set_property_h("memory.memsw.limit_in_bytes", "%dM"%(mem/2), pwd)
ps.stdin.write('\n')
i = 0
while ps.poll() == None:
@@ -352,15 +352,15 @@ class cgroup(test.test):
try:
# Available cpus: cpuset.cpus = "0-$CPUS\n"
- no_cpus = int(item.get_prop("cpuset.cpus").split('-')[1]) + 1
+ no_cpus = int(item.get_property("cpuset.cpus")[0].split('-')[1]) + 1
except:
raise error.TestFail("Failed to get no_cpus or no_cpus = 1")
pwd = item.mk_cgroup()
try:
- tmp = item.get_prop("cpuset.cpus")
+ tmp = item.get_property("cpuset.cpus")[0]
item.set_property("cpuset.cpus", tmp, pwd)
- tmp = item.get_prop("cpuset.mems")
+ tmp = item.get_property("cpuset.mems")[0]
item.set_property("cpuset.mems", tmp, pwd)
except:
cleanup(True)
diff --git a/client/tests/cgroup/cgroup_common.py b/client/tests/cgroup/cgroup_common.py
index 7a514c6..a7229ce 100755
--- a/client/tests/cgroup/cgroup_common.py
+++ b/client/tests/cgroup/cgroup_common.py
@@ -60,7 +60,7 @@ class Cgroup(object):
"""
self.root = modules.get_pwd(self.module)
if not self.root:
- raise error.TestFail("cg.initialize(): Module %s not found"
+ raise error.TestError("cg.initialize(): Module %s not found"
% self.module)
@@ -76,7 +76,7 @@ class Cgroup(object):
else:
pwd = mkdtemp(prefix='cgroup-', dir=self.root) + '/'
except Exception, inst:
- raise error.TestFail("cg.mk_cgroup(): %s" % inst)
+ raise error.TestError("cg.mk_cgroup(): %s" % inst)
self.cgroups.append(pwd)
return pwd
@@ -94,7 +94,7 @@ class Cgroup(object):
logging.warn("cg.rm_cgroup(): Removed cgroup which wasn't created"
"using this Cgroup")
except Exception, inst:
- raise error.TestFail("cg.rm_cgroup(): %s" % inst)
+ raise error.TestError("cg.rm_cgroup(): %s" % inst)
def test(self, cmd):
@@ -143,9 +143,9 @@ class Cgroup(object):
try:
open(pwd+'/tasks', 'w').write(str(pid))
except Exception, inst:
- raise error.TestFail("cg.set_cgroup(): %s" % inst)
+ raise error.TestError("cg.set_cgroup(): %s" % inst)
if self.is_cgroup(pid, pwd):
- raise error.TestFail("cg.set_cgroup(): Setting %d pid into %s "
+ raise error.TestError("cg.set_cgroup(): Setting %d pid into %s "
"cgroup failed" % (pid, pwd))
def set_root_cgroup(self, pid):
@@ -157,20 +157,6 @@ class Cgroup(object):
return self.set_cgroup(pid, self.root)
- def get_prop(self, prop, pwd=None):
- """
- Gets one line of the property value
- @param prop: property name (file)
- @param pwd: cgroup directory
- @return: String value or None when FAILED
- """
- tmp = self.get_property(prop, pwd)
- if tmp:
- if tmp[0][-1] == '\n':
- tmp[0] = tmp[0][:-1]
- return tmp[0]
-
-
def get_property(self, prop, pwd=None):
"""
Gets the property value
@@ -181,45 +167,50 @@ class Cgroup(object):
if pwd == None:
pwd = self.root
try:
- ret = open(pwd+prop, 'r').readlines()
+ # Remove tailing '\n' from each line
+ ret = [_[:-1] for _ in open(pwd+prop, 'r').readlines()]
+ if ret:
+ return ret
+ else:
+ return [""]
except Exception, inst:
- raise error.TestFail("cg.get_property(): %s" % inst)
- else:
- return ret
+ raise error.TestError("cg.get_property(): %s" % inst)
- def set_prop(self, prop, value, pwd=None, check=True):
+ def set_property_h(self, prop, value, pwd=None, check=True, checkprop=None):
"""
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
+ @param check: check the value after setup / override checking value
+ @param checkprop: override prop when checking the value
"""
_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
+ human = {'B': 1,
+ 'K': 1024,
+ 'M': 1048576,
+ 'G': 1073741824,
+ 'T': 1099511627776
+ }
+ if human.has_key(value[-1]):
+ value = int(value[:-1]) * human[value[-1]]
except:
logging.warn("cg.set_prop() fallback into cg.set_property.")
value = _value
- self.set_property(prop, value, pwd, check)
+ self.set_property(prop, value, pwd, check, checkprop)
- def set_property(self, prop, value, pwd=None, check=True):
+ def set_property(self, prop, value, pwd=None, check=True, checkprop=None):
"""
Sets the property value
@param prop: property name (file)
@param value: desired value
@param pwd: cgroup directory
- @param check: check the value after setup
+ @param check: check the value after setup / override checking value
+ @param checkprop: override prop when checking the value
"""
value = str(value)
if pwd == None:
@@ -227,14 +218,17 @@ class Cgroup(object):
try:
open(pwd+prop, 'w').write(value)
except Exception, inst:
- 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:
- raise error.TestFail("cg.set_property(): Setting failed: "
- "desired = %s, real value = %s"
- % (value, _value))
+ raise error.TestError("cg.set_property(): %s" % inst)
+ if check != False:
+ if check == True:
+ check = value
+ if checkprop == None:
+ checkprop = prop
+ _values = self.get_property(checkprop, pwd)
+ if check not in _values:
+ raise error.TestError("cg.set_property(): Setting failed: "
+ "desired = %s, real values = %s"
+ % (repr(check), repr(_values)))
def smoke_test(self):
@@ -246,14 +240,14 @@ class Cgroup(object):
ps = self.test("smoke")
if ps == None:
- raise error.TestFail("cg.smoke_test: Couldn't create process")
+ raise error.TestError("cg.smoke_test: Couldn't create process")
if (ps.poll() != None):
- raise error.TestFail("cg.smoke_test: Process died unexpectidly")
+ raise error.TestError("cg.smoke_test: Process died unexpectidly")
# New process should be a root member
if self.is_root_cgroup(ps.pid):
- raise error.TestFail("cg.smoke_test: Process is not a root member")
+ raise error.TestError("cg.smoke_test: Process is not a root member")
# Change the cgroup
self.set_cgroup(ps.pid, pwd)
@@ -261,10 +255,10 @@ class Cgroup(object):
# Try to remove used cgroup
try:
self.rm_cgroup(pwd)
- except error.TestFail:
+ except error.TestError:
pass
else:
- raise error.TestFail("cg.smoke_test: Unexpected successful deletion"
+ raise error.TestError("cg.smoke_test: Unexpected successful deletion"
" of the used cgroup")
# Return the process into the root cgroup
@@ -277,7 +271,7 @@ class Cgroup(object):
ps.stdin.write('\n')
time.sleep(2)
if (ps.poll() == None):
- raise error.TestFail("cg.smoke_test: Process is not finished")
+ raise error.TestError("cg.smoke_test: Process is not finished")
class CgroupModules(object):
@@ -316,13 +310,13 @@ class CgroupModules(object):
"""
logging.debug("Desired cgroup modules: %s", _modules)
mounts = []
- fp = open('/proc/mounts', 'r')
- line = fp.readline().split()
+ proc_mounts = open('/proc/mounts', 'r')
+ line = proc_mounts.readline().split()
while line:
if line[2] == 'cgroup':
mounts.append(line)
- line = fp.readline().split()
- fp.close()
+ line = proc_mounts.readline().split()
+ proc_mounts.close()
for module in _modules:
# Is it already mounted?
--
1.7.6.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/4] [kvm-autotest] cgroup-kvm: New subtest: TestBlkioThrottle*
2011-10-07 18:24 [kvm-autotest] cgroup-kvm: Four new BlkioThrottle tests Lukas Doktor
` (2 preceding siblings ...)
2011-10-07 18:24 ` [PATCH 3/4] [autotest] cgroup: {set,get}_property functions unification, bugfixies Lukas Doktor
@ 2011-10-07 18:24 ` Lukas Doktor
2011-10-07 18:43 ` [kvm-autotest] cgroup-kvm: Four new BlkioThrottle tests Lukáš Doktor
2011-10-11 20:30 ` Lucas Meneghel Rodrigues
5 siblings, 0 replies; 10+ messages in thread
From: Lukas Doktor @ 2011-10-07 18:24 UTC (permalink / raw)
To: autotest, kvm, kvm-autotest, akong, lmr, ldoktor, jzupka
* Four new subtests for testing blkio.throttle.{read,write}_bps_device
cgroup functionalities.
* TestBlkioThrottleRead/Write let dd read/write for 1 minute and verifies
the correct throughput.
* TestBlkioThrottleMultipleRead/Write let dd read/write while switching
multiple cgroups with different speed limits and verifies the correct
behaviour.
Signed-off-by: Lukas Doktor <ldoktor@redhat.com>
---
client/tests/kvm/tests/cgroup.py | 371 ++++++++++++++++++++++++++++++++++----
1 files changed, 331 insertions(+), 40 deletions(-)
diff --git a/client/tests/kvm/tests/cgroup.py b/client/tests/kvm/tests/cgroup.py
index 415b334..7f00a6b 100644
--- a/client/tests/kvm/tests/cgroup.py
+++ b/client/tests/kvm/tests/cgroup.py
@@ -4,9 +4,9 @@ cgroup autotest test (on KVM guest)
@copyright: 2011 Red Hat, Inc.
"""
import logging, re, sys, tempfile, time, traceback
+from random import random
from autotest_lib.client.common_lib import error
from autotest_lib.client.bin import utils
-from client.virt import virt_vm
from autotest_lib.client.tests.cgroup.cgroup_common import Cgroup, CgroupModules
def run_cgroup(test, params, env):
@@ -18,6 +18,71 @@ def run_cgroup(test, params, env):
tests = None
# Func
+ def _check_vms(vms):
+ """
+ Checks if the VM is alive.
+ @param vms: list of vm's
+ """
+ for i in range(len(vms)):
+ vms[i].verify_alive()
+ try:
+ vms[i].verify_kernel_crash()
+ vms[i].wait_for_login(timeout=30).close()
+ except Exception, failure_detail:
+ logging.error("_check_vms: %s", failure_detail)
+ logging.warn("recreate VM(%s)", i)
+ # The vm has to be recreated to reset the qemu PCI state
+ vms[i].create()
+
+
+ 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
+
+
+ def distance(actual, reference):
+ """
+ Absolute value of relative distance of two numbers
+ @param actual: actual value
+ @param reference: reference value
+ @return: relative distance abs((a-r)/r) (float)
+ """
+ return abs(float(actual-reference) / reference)
+
+
+ def get_dd_cmd(direction, dev='vd?', count=None, bs=None):
+ """
+ Generates dd_cmd string
+ @param direction: {read,write,bi} dd direction
+ @param dev: used device ('vd?')
+ @param count: count parameter of dd
+ @param bs: bs parameter of dd
+ @return: dd command string
+ """
+ if direction == "read":
+ params = "if=$FILE of=/dev/null iflag=direct"
+ elif direction == "write":
+ params = "if=/dev/zero of=$FILE oflag=direct"
+ else:
+ params = "if=$FILE of=$FILE iflag=direct oflag=direct"
+ if bs:
+ params += " bs=%s" % (bs)
+ if count:
+ params += " count=%s" % (count)
+ return ("export FILE=$(ls /dev/%s | tail -n 1); touch /tmp/cgroup_lock "
+ "; while [ -e /tmp/cgroup_lock ]; do dd %s ; done"
+ % (dev, params))
+
+
def get_device_driver():
"""
Discovers the used block device driver {ide, scsi, virtio_blk}
@@ -41,14 +106,17 @@ def run_cgroup(test, params, env):
ret_file: created file handler (None if not created)
device: PCI id of the virtual disk
"""
+ # TODO: Implement also via QMP
if not host_file:
host_file = tempfile.NamedTemporaryFile(prefix="cgroup-disk-",
suffix=".iso")
utils.system("dd if=/dev/zero of=%s bs=1M count=8 &>/dev/null"
% (host_file.name))
ret_file = host_file
+ logging.debug("add_file_drive: new file %s as drive", host_file)
else:
ret_file = None
+ logging.debug("add_file_drive: using file %s as drive", host_file)
out = vm.monitor.cmd("pci_add auto storage file=%s,if=%s,snapshot=off,"
"cache=off" % (host_file.name, driver))
@@ -71,19 +139,25 @@ def run_cgroup(test, params, env):
ret_file: string of the created dev (None if not created)
device: PCI id of the virtual disk
"""
+ # TODO: Implement also via QMP
if not host_file:
- if utils.system_output("lsmod | grep scsi_debug -c") == 0:
+ if utils.system("lsmod | grep scsi_debug", ignore_status=True):
utils.system("modprobe scsi_debug dev_size_mb=8 add_host=0")
utils.system("echo 1 > /sys/bus/pseudo/drivers/scsi_debug/add_host")
+ time.sleep(1) # Wait for device init
host_file = utils.system_output("ls /dev/sd* | tail -n 1")
# Enable idling in scsi_debug drive
- utils.system("echo 1 > /sys/block/%s/queue/rotational" % host_file)
+ utils.system("echo 1 > /sys/block/%s/queue/rotational"
+ % (host_file.split('/')[-1]))
ret_file = host_file
+ logging.debug("add_scsi_drive: add %s device", host_file)
else:
# Don't remove this device during cleanup
# Reenable idling in scsi_debug drive (in case it's not)
- utils.system("echo 1 > /sys/block/%s/queue/rotational" % host_file)
+ utils.system("echo 1 > /sys/block/%s/queue/rotational"
+ % (host_file.split('/')[-1]))
ret_file = None
+ logging.debug("add_scsi_drive: using %s device", host_file)
out = vm.monitor.cmd("pci_add auto storage file=%s,if=%s,snapshot=off,"
"cache=off" % (host_file, driver))
@@ -101,15 +175,17 @@ def run_cgroup(test, params, env):
Remove drive from vm and device on disk
! beware to remove scsi devices in reverse order !
"""
+ # TODO: Implement also via QMP
vm.monitor.cmd("pci_del %s" % device)
if isinstance(host_file, file): # file
host_file.close()
- elif isinstance(host_file, str): # scsi device
- utils.system("echo -1> /sys/bus/pseudo/drivers/scsi_debug/add_host")
+ elif isinstance(host_file, str): # scsi devaice
+ utils.system("echo -1 >/sys/bus/pseudo/drivers/scsi_debug/add_host")
else: # custom file, do nothing
pass
+
def get_all_pids(ppid):
"""
Get all PIDs of children/threads of parent ppid
@@ -119,6 +195,7 @@ def run_cgroup(test, params, env):
return (utils.system_output("ps -L --ppid=%d -o lwp" % ppid)
.split('\n')[1:])
+
# Tests
class _TestBlkioBandwidth:
"""
@@ -181,8 +258,7 @@ def run_cgroup(test, params, env):
# cgroups
pwd = []
blkio = self.blkio
- if blkio.initialize(self.modules):
- raise error.TestError("Could not initialize blkio Cgroup")
+ blkio.initialize(self.modules)
for i in range(2):
pwd.append(blkio.mk_cgroup())
blkio.set_cgroup(self.vms[i].get_shell_pid(), pwd[i])
@@ -192,8 +268,6 @@ def run_cgroup(test, params, env):
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.
for i in range(2):
(host_file, device) = add_file_drive(vms[i], "virtio")
self.files.append(host_file)
@@ -263,10 +337,7 @@ def run_cgroup(test, params, env):
_TestBlkioBandwidth.__init__(self, vms, modules)
# Read from the last vd* in a loop until test removes the
# /tmp/cgroup_lock file (and kills us)
- self.dd_cmd = ("export FILE=$(ls /dev/vd* | tail -n 1); touch "
- "/tmp/cgroup_lock ; while [ -e /tmp/cgroup_lock ];"
- "do dd if=$FILE of=/dev/null iflag=direct bs=100K;"
- "done")
+ self.dd_cmd = get_dd_cmd("read", bs="100K")
class TestBlkioBandwidthWeigthWrite(_TestBlkioBandwidth):
@@ -282,45 +353,266 @@ def run_cgroup(test, params, env):
# Write on the last vd* in a loop until test removes the
# /tmp/cgroup_lock file (and kills us)
_TestBlkioBandwidth.__init__(self, vms, modules)
- self.dd_cmd = ('export FILE=$(ls /dev/vd* | tail -n 1); touch '
- '/tmp/cgroup_lock ; while [ -e /tmp/cgroup_lock ];'
- 'do dd if=/dev/zero of=$FILE oflag=direct bs=100K;'
- 'done')
+ self.dd_cmd = get_dd_cmd("write", bs="100K")
- def _check_vms(vms):
+ class _TestBlkioThrottle:
"""
- Checks if the VM is alive.
- @param vms: list of vm's
+ BlkioThrottle dummy test
+ * Use it as a base class to an actual test!
+ * self.dd_cmd and throughputs have to be implemented
+ * It prepares a vm and runs self.dd_cmd. Always after 1 minute switches
+ the cgroup. At the end verifies, that the throughputs matches the
+ theoretical values.
"""
- for i in range(len(vms)):
- vms[i].verify_alive()
+ def __init__(self, vms, modules):
+ """
+ Initialization
+ @param vms: list of vms
+ @param modules: initialized cgroup module class
+ """
+ self.vm = vms[0] # Virt machines
+ self.modules = modules # cgroup module handler
+ self.cgroup = Cgroup('blkio', '') # cgroup blkio handler
+ self.cgroups = [] # List of cgroups directories
+ self.files = None # Temporary files (files of virt disks)
+ self.devices = None # Temporary virt devices (PCI drive 1 per vm)
+ self.dd_cmd = None # DD command used to test the throughput
+ self.speeds = None # cgroup throughput
+
+ def cleanup(self):
+ """
+ Cleanup
+ """
+ err = ""
try:
- vms[i].verify_kernel_crash()
- except virt_vm.VMDeadKernelCrashError, failure_detail:
- logging.error("_check_vms: %s", failure_detail)
- logging.warn("recreate VM(%s)", i)
- # The vm has to be recreated to reset the qemu PCI state
- vms[i].create()
+ rm_drive(self.vm, self.files, self.devices)
+ except Exception, failure_detail:
+ err += "\nCan't remove PCI drive: %s" % failure_detail
+ try:
+ del(self.cgroup)
+ except Exception, failure_detail:
+ err += "\nCan't remove Cgroup: %s" % failure_detail
- def _traceback(name, exc_info):
+ if err:
+ logging.error("Some cleanup operations failed: %s", err)
+ raise error.TestError("Some cleanup operations failed: %s"
+ % err)
+
+ def init(self):
+ """
+ Initialization
+ * creates a new virtio device and adds it into vm
+ * creates a cgroup for each throughput
+ """
+ if (self.dd_cmd is None) or (self.speeds) is None:
+ raise error.TestError("Corrupt class, aren't you trying to run "
+ "parent _TestBlkioThrottle() function?")
+
+ (self.files, self.devices) = add_scsi_drive(self.vm)
+ try:
+ dev = utils.system_output("ls -l %s" % self.files).split()[4:6]
+ dev[0] = dev[0][:-1] # Remove tailing ','
+ except:
+ time.sleep(5)
+ raise error.TestFail("Couldn't get %s maj and min numbers"
+ % self.files)
+
+ cgroup = self.cgroup
+ cgroup.initialize(self.modules)
+ for i in range(len(self.speeds)):
+ speed = self.speeds[i]
+ self.cgroups.append(cgroup.mk_cgroup())
+ if speed == 0: # Disable limit (removes the limit)
+ cgroup.set_property("blkio.throttle.write_bps_device",
+ "%s:%s %s" % (dev[0], dev[1], speed),
+ check="")
+ cgroup.set_property("blkio.throttle.read_bps_device",
+ "%s:%s %s" % (dev[0], dev[1], speed),
+ check="")
+ else: # Enable limit (input separator ' ', output '\t')
+ cgroup.set_property("blkio.throttle.write_bps_device",
+ "%s:%s %s" % (dev[0], dev[1], speed),
+ self.cgroups[i], check="%s:%s\t%s"
+ % (dev[0], dev[1], speed))
+ cgroup.set_property("blkio.throttle.read_bps_device",
+ "%s:%s %s" % (dev[0], dev[1], speed),
+ self.cgroups[i], check="%s:%s\t%s"
+ % (dev[0], dev[1], speed))
+
+ def run(self):
+ """
+ Actual test:
+ * executes self.dd_cmd in vm while limiting it's throughput using
+ different cgroups (or in a special case only one). At the end
+ it verifies the throughputs.
+ """
+ out = []
+ sessions = []
+ sessions.append(self.vm.wait_for_login(timeout=30))
+ sessions.append(self.vm.wait_for_login(timeout=30))
+ sessions[0].sendline(self.dd_cmd)
+ for i in range(len(self.cgroups)):
+ logging.info("Limiting speed to: %s", (self.speeds[i]))
+ # Assign all threads of vm
+ self.cgroup.set_cgroup(self.vm.get_shell_pid(), self.cgroups[i])
+ for pid in get_all_pids(self.vm.get_shell_pid()):
+ self.cgroup.set_cgroup(int(pid), self.cgroups[i])
+
+ # Standard test-time is 60s. If the slice time is less than 30s,
+ # test-time is prolonged to 30s per slice.
+ time.sleep(max(60/len(self.speeds), 30))
+ sessions[1].sendline("rm -f /tmp/cgroup_lock; killall -9 dd")
+ out.append(sessions[0].read_up_to_prompt())
+ sessions[0].sendline(self.dd_cmd)
+ time.sleep(random()*0.05)
+
+ sessions[1].sendline("rm -f /tmp/cgroup_lock; killall -9 dd")
+ # Verification
+ re_dd = (r'(\d+) bytes \(\d+\.*\d* \w*\) copied, (\d+\.*\d*) s, '
+ '\d+\.*\d* \w./s')
+ err = []
+ for i in range(len(out)):
+ out[i] = [int(_[0])/float(_[1])
+ for _ in re.findall(re_dd, out[i])]
+ if not out[i]:
+ raise error.testFail("Not enough samples; please increase"
+ "throughput speed or testing time;"
+ "\nsamples: %s" % (out[i]))
+ # First samples might be corrupted, use only last sample when
+ # not enough data. (which are already an avg of 3xBS)
+ warn = False
+ if len(out[i]) < 3:
+ warn = True
+ out[i] = [out[i][-1]]
+ count = len(out[i])
+ out[i].sort()
+ # out = [min, med, max, number_of_samples]
+ out[i] = [out[i][0], out[i][count/2], out[i][-1], count]
+ if warn:
+ logging.warn("Not enough samples, using the last one (%s)",
+ out[i])
+ if ((self.speeds[i] != 0) and
+ (distance(out[i][1], self.speeds[i]) > 0.1)):
+ logging.error("The throughput didn't match the requirements"
+ "(%s !~ %s)", out[i], self.speeds[i])
+ err.append(i)
+
+ if self.speeds.count(0) > 1:
+ unlimited = []
+ for i in range(len(self.speeds)):
+ if self.speeds[i] == 0:
+ unlimited.append(out[i][1])
+ self.speeds[i] = "(inf)"
+
+ avg = sum(unlimited) / len(unlimited)
+ if avg == 0:
+ logging.warn("Average unlimited speed is 0 (%s)", out)
+ else:
+ for speed in unlimited:
+ if distance(speed, avg) > 0.1:
+ logging.warning("Unlimited speeds variates during "
+ "the test: %s", unlimited)
+
+
+ out_speeds = ["%s ~ %s" % (out[i][1], self.speeds[i])
+ for i in range(len(self.speeds))]
+ if err:
+ if len(out) == 1:
+ raise error.TestFail("Actual throughput: %s, theoretical: "
+ "%s" % (out[0][1], self.speeds[0]))
+ elif len(err) == len(out):
+ raise error.TestFail("All throughput limits were broken "
+ "(%s)" % (out_speeds))
+ else:
+ raise error.TestFail("Limits (%s) were broken (%s)"
+ % (err, out_speeds))
+
+ return ("All throughputs matched their limits (%s)" % out_speeds)
+
+
+ class TestBlkioThrottleRead(_TestBlkioThrottle):
+ """ Tests the blkio.throttle.read_bps_device """
+ def __init__(self, vms, modules):
+ """
+ Initialization
+ @param vms: list of vms
+ @param modules: initialized cgroup module class
+ """
+ _TestBlkioThrottle.__init__(self, vms, modules)
+ if get_device_driver() == "virtio":
+ dev = "vd?"
+ else:
+ dev = "[sh]d?"
+ self.dd_cmd = get_dd_cmd("read", dev=dev, count=8)
+ self.speeds = [1024]
+
+
+ class TestBlkioThrottleWrite(_TestBlkioThrottle):
+ """ Tests the blkio.throttle.write_bps_device """
+ def __init__(self, vms, modules):
+ """
+ Initialization
+ @param vms: list of vms
+ @param modules: initialized cgroup module class
+ """
+ _TestBlkioThrottle.__init__(self, vms, modules)
+ if get_device_driver() == "virtio":
+ dev = "vd?"
+ else:
+ dev = "[sh]d?"
+ self.dd_cmd = get_dd_cmd("write", dev=dev, count=8)
+ self.speeds = [1024]
+
+
+ class TestBlkioThrottleMultipleRead(_TestBlkioThrottle):
"""
- 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
+ Tests the blkio.throttle.read_bps_device while switching multiple
+ cgroups with different speeds.
"""
- out = "\n"
- for line in traceback.format_exception(exc_info[0], exc_info[1],
- exc_info[2]):
- out += "%s: %s" % (name, line)
- return out
+ def __init__(self, vms, modules):
+ """
+ Initialization
+ @param vms: list of vms
+ @param modules: initialized cgroup module class
+ """
+ _TestBlkioThrottle.__init__(self, vms, modules)
+ if get_device_driver() == "virtio":
+ dev = "vd?"
+ else:
+ dev = "[sh]d?"
+ self.dd_cmd = get_dd_cmd("read", dev=dev, count=3)
+ self.speeds = [0, 1024, 0, 2048, 0, 4096]
+
+
+ class TestBlkioThrottleMultipleWrite(_TestBlkioThrottle):
+ """
+ Tests the blkio.throttle.write_bps_device while switching multiple
+ cgroups with different speeds.
+ """
+ def __init__(self, vms, modules):
+ """
+ Initialization
+ @param vms: list of vms
+ @param modules: initialized cgroup module class
+ """
+ _TestBlkioThrottle.__init__(self, vms, modules)
+ if get_device_driver() == "virtio":
+ dev = "vd?"
+ else:
+ dev = "[sh]d?"
+ self.dd_cmd = get_dd_cmd("write", dev=dev, count=3)
+ self.speeds = [0, 1024, 0, 2048, 0, 4096]
# Setup
# TODO: Add all new tests here
tests = {"blkio_bandwidth_weigth_read" : TestBlkioBandwidthWeigthRead,
"blkio_bandwidth_weigth_write" : TestBlkioBandwidthWeigthWrite,
+ "blkio_throttle_read" : TestBlkioThrottleRead,
+ "blkio_throttle_write" : TestBlkioThrottleWrite,
+ "blkio_throttle_multiple_read" : TestBlkioThrottleMultipleRead,
+ "blkio_throttle_multiple_write" : TestBlkioThrottleMultipleWrite,
}
modules = CgroupModules()
if (modules.init(['blkio']) <= 0):
@@ -407,4 +699,3 @@ def run_cgroup(test, params, env):
logging.info(out)
if results.count("FAILED"):
raise error.TestFail("Some subtests failed\n%s" % out)
-
--
1.7.6.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [kvm-autotest] cgroup-kvm: Four new BlkioThrottle tests
2011-10-07 18:24 [kvm-autotest] cgroup-kvm: Four new BlkioThrottle tests Lukas Doktor
` (3 preceding siblings ...)
2011-10-07 18:24 ` [PATCH 4/4] [kvm-autotest] cgroup-kvm: New subtest: TestBlkioThrottle* Lukas Doktor
@ 2011-10-07 18:43 ` Lukáš Doktor
2011-10-11 20:30 ` Lucas Meneghel Rodrigues
5 siblings, 0 replies; 10+ messages in thread
From: Lukáš Doktor @ 2011-10-07 18:43 UTC (permalink / raw)
To: Lukas Doktor; +Cc: autotest, kvm, kvm-autotest, akong, lmr, jzupka
Dne 7.10.2011 20:24, Lukas Doktor napsal(a):
> This is a patchset with four new tests to KVM specific cgroup testing. Also I made some modifications into (general) cgroup_common library which makes cgroup testing better readable and more safe to execute. Please find the details in each patch.
>
> Also please beware of qemu-kvm bugs which occurred for me (qemu-kvm 0.15.0 F17) which led to qemu SEGFAULTS or even to dysfunction (qemu-kvm 0.14 F15). I'll fill in Bugzilla on Monday.
>
> This was also sent as a github pull request, so if you feel like commenting on the pull request, be my guest:
> https://github.com/autotest/autotest/pull/33
>
> Best regards,
> Lukáš
Already one minor change, please follow the patches on github...
diff --git a/client/tests/kvm/tests/cgroup.py
b/client/tests/kvm/tests/cgroup.py
index 7f00a6b..7407e29 100644
--- a/client/tests/kvm/tests/cgroup.py
+++ b/client/tests/kvm/tests/cgroup.py
@@ -409,7 +409,13 @@ def run_cgroup(test, params, env):
raise error.TestError("Corrupt class, aren't you
trying to run
"parent _TestBlkioThrottle()
function?")
- (self.files, self.devices) = add_scsi_drive(self.vm)
+ if get_device_driver() == "ide":
+ logging.warn("The main disk for this VM is ide wich
doesn't "
+ "support hot-plug. Using virtio_blk instead")
+ (self.files, self.devices) = add_scsi_drive(self.vm,
+
driver="virtio")
+ else:
+ (self.files, self.devices) = add_scsi_drive(self.vm)
try:
dev = utils.system_output("ls -l %s" %
self.files).split()[4:6]
dev[0] = dev[0][:-1] # Remove tailing ','
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/4] [kvm-autotest] cgroup-kvm: add_*_drive / rm_drive
2011-10-07 18:24 ` [PATCH 1/4] [kvm-autotest] cgroup-kvm: add_*_drive / rm_drive Lukas Doktor
@ 2011-10-10 10:26 ` Jiri Zupka
2011-10-10 10:37 ` Lukáš Doktor
0 siblings, 1 reply; 10+ messages in thread
From: Jiri Zupka @ 2011-10-10 10:26 UTC (permalink / raw)
To: Lukas Doktor; +Cc: autotest, kvm-autotest, kvm
This is useful function. This function can be in kvm utils.
----- Original Message -----
> * functions for adding and removal of drive to vm using host-file or
> host-scsi_debug device.
>
> Signed-off-by: Lukas Doktor <ldoktor@redhat.com>
> ---
> client/tests/kvm/tests/cgroup.py | 125
> ++++++++++++++++++++++++++++++++-----
> 1 files changed, 108 insertions(+), 17 deletions(-)
>
> diff --git a/client/tests/kvm/tests/cgroup.py
> b/client/tests/kvm/tests/cgroup.py
> index b9a10ea..d6418b5 100644
> --- a/client/tests/kvm/tests/cgroup.py
> +++ b/client/tests/kvm/tests/cgroup.py
> @@ -17,6 +17,108 @@ def run_cgroup(test, params, env):
> vms = None
> tests = None
>
> + # Func
> + def get_device_driver():
> + """
> + Discovers the used block device driver {ide, scsi,
> virtio_blk}
> + @return: Used block device driver {ide, scsi, virtio}
> + """
> + if test.tagged_testname.count('virtio_blk'):
> + return "virtio"
> + elif test.tagged_testname.count('scsi'):
> + return "scsi"
> + else:
> + return "ide"
> +
> +
> + def add_file_drive(vm, driver=get_device_driver(),
> host_file=None):
> + """
> + Hot-add a drive based on file to a vm
> + @param vm: Desired VM
> + @param driver: which driver should be used (default: same as
> in test)
> + @param host_file: Which file on host is the image (default:
> create new)
> + @return: Tupple(ret_file, device)
> + ret_file: created file handler (None if not
> created)
> + device: PCI id of the virtual disk
> + """
> + if not host_file:
> + host_file =
> tempfile.NamedTemporaryFile(prefix="cgroup-disk-",
> + suffix=".iso")
> + utils.system("dd if=/dev/zero of=%s bs=1M count=8
> &>/dev/null"
> + % (host_file.name))
> + ret_file = host_file
> + else:
> + ret_file = None
> +
> + out = vm.monitor.cmd("pci_add auto storage
> file=%s,if=%s,snapshot=off,"
> + "cache=off" % (host_file.name, driver))
> + dev = re.search(r'OK domain (\d+), bus (\d+), slot (\d+),
> function \d+',
> + out)
> + if not dev:
> + raise error.TestFail("Can't add device(%s, %s, %s): %s"
> % (vm,
> + host_file.name,
> driver, out))
> + device = "%s:%s:%s" % dev.groups()
> + return (ret_file, device)
> +
> +
> + def add_scsi_drive(vm, driver=get_device_driver(),
> host_file=None):
> + """
> + Hot-add a drive based on scsi_debug device to a vm
> + @param vm: Desired VM
> + @param driver: which driver should be used (default: same as
> in test)
> + @param host_file: Which dev on host is the image (default:
> create new)
> + @return: Tupple(ret_file, device)
> + ret_file: string of the created dev (None if not
> created)
> + device: PCI id of the virtual disk
> + """
> + if not host_file:
> + if utils.system_output("lsmod | grep scsi_debug -c") ==
> 0:
> + utils.system("modprobe scsi_debug dev_size_mb=8
> add_host=0")
> + utils.system("echo 1 >
> /sys/bus/pseudo/drivers/scsi_debug/add_host")
> + host_file = utils.system_output("ls /dev/sd* | tail -n
> 1")
> + # Enable idling in scsi_debug drive
> + utils.system("echo 1 > /sys/block/%s/queue/rotational" %
> host_file)
> + ret_file = host_file
> + else:
> + # Don't remove this device during cleanup
> + # Reenable idling in scsi_debug drive (in case it's not)
> + utils.system("echo 1 > /sys/block/%s/queue/rotational" %
> host_file)
> + ret_file = None
> +
> + out = vm.monitor.cmd("pci_add auto storage
> file=%s,if=%s,snapshot=off,"
> + "cache=off" % (host_file, driver))
> + dev = re.search(r'OK domain (\d+), bus (\d+), slot (\d+),
> function \d+',
> + out)
> + if not dev:
> + raise error.TestFail("Can't add device(%s, %s, %s): %s"
> % (vm,
> + host_file,
> driver, out))
> + device = "%s:%s:%s" % dev.groups()
> + return (ret_file, device)
> +
> +
> + def rm_drive(vm, host_file, device):
> + """
> + Remove drive from vm and device on disk
> + ! beware to remove scsi devices in reverse order !
> + """
> + vm.monitor.cmd("pci_del %s" % device)
> +
> + if isinstance(host_file, file): # file
> + host_file.close()
> + elif isinstance(host_file, str): # scsi device
> + utils.system("echo -1>
> /sys/bus/pseudo/drivers/scsi_debug/add_host")
> + else: # custom file, do nothing
> + pass
> +
> + def get_all_pids(ppid):
> + """
> + Get all PIDs of children/threads of parent ppid
> + param ppid: parent PID
> + return: list of PIDs of all children/threads of ppid
> + """
> + return (utils.system_output("ps -L --ppid=%d -o lwp" % ppid)
> +
> .split('\n')[1:])
> +
> # Tests
> class _TestBlkioBandwidth:
> """
> @@ -46,9 +148,8 @@ def run_cgroup(test, params, env):
> """
> err = ""
> try:
> - for i in range (2):
> - vms[i].monitor.cmd("pci_del %s" %
> self.devices[i])
> - self.files[i].close()
> + for i in range(1, -1, -1):
> + rm_drive(vms[i], self.files[i], self.devices[i])
> except Exception, failure_detail:
> err += "\nCan't remove PCI drive: %s" %
> failure_detail
> try:
> @@ -89,8 +190,7 @@ def run_cgroup(test, params, env):
> if blkio.set_cgroup(self.vms[i].get_shell_pid(),
> pwd[i]):
> raise error.TestError("Could not set cgroup")
> # Move all existing threads into cgroup
> - for tmp in utils.system_output("ps -L --ppid=%d -o
> lwp"
> - %
> self.vms[i].get_shell_pid()).split('\n')[1:]:
> + 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]):
> @@ -101,18 +201,9 @@ def run_cgroup(test, params, env):
> # Add dummy drives
> # TODO: implement also using QMP.
> for i in range(2):
> - self.files.append(tempfile.NamedTemporaryFile(
> - prefix="cgroup-disk-",
> - suffix=".iso"))
> - utils.system("dd if=/dev/zero of=%s bs=1M count=10
> &>/dev/null"
> - % (self.files[i].name))
> - out = vms[i].monitor.cmd("pci_add auto storage
> file=%s,"
> - "if=virtio,snapshot=off,cache=off"
> - % (self.files[i].name))
> - out = re.search(r'OK domain (\d+), bus (\d+), slot
> (\d+), '
> - 'function \d+', out).groups()
> - self.devices.append("%s:%s:%s" % out)
> -
> + (host_file, device) = add_file_drive(vms[i],
> "virtio")
> + self.files.append(host_file)
> + self.devices.append(device)
>
> def run(self):
> """
> --
> 1.7.6.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/4] [kvm-autotest] cgroup-kvm: add_*_drive / rm_drive
2011-10-10 10:26 ` Jiri Zupka
@ 2011-10-10 10:37 ` Lukáš Doktor
2011-10-11 17:13 ` Lucas Meneghel Rodrigues
0 siblings, 1 reply; 10+ messages in thread
From: Lukáš Doktor @ 2011-10-10 10:37 UTC (permalink / raw)
To: Jiri Zupka; +Cc: autotest, kvm, kvm-autotest, akong, lmr
I thought about that. But pci_add is not much stable and it's not
supported in QMP (as far as I read) with a note that this way is buggy
and should be rewritten completely. So I placed it here to let it
develop and then I can move it into utils.
Regards,
Lukáš
Dne 10.10.2011 12:26, Jiri Zupka napsal(a):
> This is useful function. This function can be in kvm utils.
>
> ----- Original Message -----
>> * functions for adding and removal of drive to vm using host-file or
>> host-scsi_debug device.
>>
>> Signed-off-by: Lukas Doktor<ldoktor@redhat.com>
>> ---
>> client/tests/kvm/tests/cgroup.py | 125
>> ++++++++++++++++++++++++++++++++-----
>> 1 files changed, 108 insertions(+), 17 deletions(-)
>>
>> diff --git a/client/tests/kvm/tests/cgroup.py
>> b/client/tests/kvm/tests/cgroup.py
>> index b9a10ea..d6418b5 100644
>> --- a/client/tests/kvm/tests/cgroup.py
>> +++ b/client/tests/kvm/tests/cgroup.py
>> @@ -17,6 +17,108 @@ def run_cgroup(test, params, env):
>> vms = None
>> tests = None
>>
>> + # Func
>> + def get_device_driver():
>> + """
>> + Discovers the used block device driver {ide, scsi,
>> virtio_blk}
>> + @return: Used block device driver {ide, scsi, virtio}
>> + """
>> + if test.tagged_testname.count('virtio_blk'):
>> + return "virtio"
>> + elif test.tagged_testname.count('scsi'):
>> + return "scsi"
>> + else:
>> + return "ide"
>> +
>> +
>> + def add_file_drive(vm, driver=get_device_driver(),
>> host_file=None):
>> + """
>> + Hot-add a drive based on file to a vm
>> + @param vm: Desired VM
>> + @param driver: which driver should be used (default: same as
>> in test)
>> + @param host_file: Which file on host is the image (default:
>> create new)
>> + @return: Tupple(ret_file, device)
>> + ret_file: created file handler (None if not
>> created)
>> + device: PCI id of the virtual disk
>> + """
>> + if not host_file:
>> + host_file =
>> tempfile.NamedTemporaryFile(prefix="cgroup-disk-",
>> + suffix=".iso")
>> + utils.system("dd if=/dev/zero of=%s bs=1M count=8
>> &>/dev/null"
>> + % (host_file.name))
>> + ret_file = host_file
>> + else:
>> + ret_file = None
>> +
>> + out = vm.monitor.cmd("pci_add auto storage
>> file=%s,if=%s,snapshot=off,"
>> + "cache=off" % (host_file.name, driver))
>> + dev = re.search(r'OK domain (\d+), bus (\d+), slot (\d+),
>> function \d+',
>> + out)
>> + if not dev:
>> + raise error.TestFail("Can't add device(%s, %s, %s): %s"
>> % (vm,
>> + host_file.name,
>> driver, out))
>> + device = "%s:%s:%s" % dev.groups()
>> + return (ret_file, device)
>> +
>> +
>> + def add_scsi_drive(vm, driver=get_device_driver(),
>> host_file=None):
>> + """
>> + Hot-add a drive based on scsi_debug device to a vm
>> + @param vm: Desired VM
>> + @param driver: which driver should be used (default: same as
>> in test)
>> + @param host_file: Which dev on host is the image (default:
>> create new)
>> + @return: Tupple(ret_file, device)
>> + ret_file: string of the created dev (None if not
>> created)
>> + device: PCI id of the virtual disk
>> + """
>> + if not host_file:
>> + if utils.system_output("lsmod | grep scsi_debug -c") ==
>> 0:
>> + utils.system("modprobe scsi_debug dev_size_mb=8
>> add_host=0")
>> + utils.system("echo 1>
>> /sys/bus/pseudo/drivers/scsi_debug/add_host")
>> + host_file = utils.system_output("ls /dev/sd* | tail -n
>> 1")
>> + # Enable idling in scsi_debug drive
>> + utils.system("echo 1> /sys/block/%s/queue/rotational" %
>> host_file)
>> + ret_file = host_file
>> + else:
>> + # Don't remove this device during cleanup
>> + # Reenable idling in scsi_debug drive (in case it's not)
>> + utils.system("echo 1> /sys/block/%s/queue/rotational" %
>> host_file)
>> + ret_file = None
>> +
>> + out = vm.monitor.cmd("pci_add auto storage
>> file=%s,if=%s,snapshot=off,"
>> + "cache=off" % (host_file, driver))
>> + dev = re.search(r'OK domain (\d+), bus (\d+), slot (\d+),
>> function \d+',
>> + out)
>> + if not dev:
>> + raise error.TestFail("Can't add device(%s, %s, %s): %s"
>> % (vm,
>> + host_file,
>> driver, out))
>> + device = "%s:%s:%s" % dev.groups()
>> + return (ret_file, device)
>> +
>> +
>> + def rm_drive(vm, host_file, device):
>> + """
>> + Remove drive from vm and device on disk
>> + ! beware to remove scsi devices in reverse order !
>> + """
>> + vm.monitor.cmd("pci_del %s" % device)
>> +
>> + if isinstance(host_file, file): # file
>> + host_file.close()
>> + elif isinstance(host_file, str): # scsi device
>> + utils.system("echo -1>
>> /sys/bus/pseudo/drivers/scsi_debug/add_host")
>> + else: # custom file, do nothing
>> + pass
>> +
>> + def get_all_pids(ppid):
>> + """
>> + Get all PIDs of children/threads of parent ppid
>> + param ppid: parent PID
>> + return: list of PIDs of all children/threads of ppid
>> + """
>> + return (utils.system_output("ps -L --ppid=%d -o lwp" % ppid)
>> +
>> .split('\n')[1:])
>> +
>> # Tests
>> class _TestBlkioBandwidth:
>> """
>> @@ -46,9 +148,8 @@ def run_cgroup(test, params, env):
>> """
>> err = ""
>> try:
>> - for i in range (2):
>> - vms[i].monitor.cmd("pci_del %s" %
>> self.devices[i])
>> - self.files[i].close()
>> + for i in range(1, -1, -1):
>> + rm_drive(vms[i], self.files[i], self.devices[i])
>> except Exception, failure_detail:
>> err += "\nCan't remove PCI drive: %s" %
>> failure_detail
>> try:
>> @@ -89,8 +190,7 @@ def run_cgroup(test, params, env):
>> if blkio.set_cgroup(self.vms[i].get_shell_pid(),
>> pwd[i]):
>> raise error.TestError("Could not set cgroup")
>> # Move all existing threads into cgroup
>> - for tmp in utils.system_output("ps -L --ppid=%d -o
>> lwp"
>> - %
>> self.vms[i].get_shell_pid()).split('\n')[1:]:
>> + 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]):
>> @@ -101,18 +201,9 @@ def run_cgroup(test, params, env):
>> # Add dummy drives
>> # TODO: implement also using QMP.
>> for i in range(2):
>> - self.files.append(tempfile.NamedTemporaryFile(
>> - prefix="cgroup-disk-",
>> - suffix=".iso"))
>> - utils.system("dd if=/dev/zero of=%s bs=1M count=10
>> &>/dev/null"
>> - % (self.files[i].name))
>> - out = vms[i].monitor.cmd("pci_add auto storage
>> file=%s,"
>> - "if=virtio,snapshot=off,cache=off"
>> - % (self.files[i].name))
>> - out = re.search(r'OK domain (\d+), bus (\d+), slot
>> (\d+), '
>> - 'function \d+', out).groups()
>> - self.devices.append("%s:%s:%s" % out)
>> -
>> + (host_file, device) = add_file_drive(vms[i],
>> "virtio")
>> + self.files.append(host_file)
>> + self.devices.append(device)
>>
>> def run(self):
>> """
>> --
>> 1.7.6.2
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe kvm" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/4] [kvm-autotest] cgroup-kvm: add_*_drive / rm_drive
2011-10-10 10:37 ` Lukáš Doktor
@ 2011-10-11 17:13 ` Lucas Meneghel Rodrigues
0 siblings, 0 replies; 10+ messages in thread
From: Lucas Meneghel Rodrigues @ 2011-10-11 17:13 UTC (permalink / raw)
To: Lukáš Doktor; +Cc: Jiri Zupka, autotest, kvm, kvm-autotest, akong
On Mon, Oct 10, 2011 at 7:37 AM, Lukáš Doktor <ldoktor@redhat.com> wrote:
> I thought about that. But pci_add is not much stable and it's not supported
> in QMP (as far as I read) with a note that this way is buggy and should be
> rewritten completely. So I placed it here to let it develop and then I can
> move it into utils.
That is right, it was removed from QMP. Now, when the time is right I
would like to see these functions as vm object methods, just like we
did with nic hotplug.
I'm reading the patchset, but in general I'm ok with leaving these
functions in the test for now.
> Regards,
> Lukáš
>
> Dne 10.10.2011 12:26, Jiri Zupka napsal(a):
>>
>> This is useful function. This function can be in kvm utils.
>>
>> ----- Original Message -----
>>>
>>> * functions for adding and removal of drive to vm using host-file or
>>> host-scsi_debug device.
>>>
>>> Signed-off-by: Lukas Doktor<ldoktor@redhat.com>
>>> ---
>>> client/tests/kvm/tests/cgroup.py | 125
>>> ++++++++++++++++++++++++++++++++-----
>>> 1 files changed, 108 insertions(+), 17 deletions(-)
>>>
>>> diff --git a/client/tests/kvm/tests/cgroup.py
>>> b/client/tests/kvm/tests/cgroup.py
>>> index b9a10ea..d6418b5 100644
>>> --- a/client/tests/kvm/tests/cgroup.py
>>> +++ b/client/tests/kvm/tests/cgroup.py
>>> @@ -17,6 +17,108 @@ def run_cgroup(test, params, env):
>>> vms = None
>>> tests = None
>>>
>>> + # Func
>>> + def get_device_driver():
>>> + """
>>> + Discovers the used block device driver {ide, scsi,
>>> virtio_blk}
>>> + @return: Used block device driver {ide, scsi, virtio}
>>> + """
>>> + if test.tagged_testname.count('virtio_blk'):
>>> + return "virtio"
>>> + elif test.tagged_testname.count('scsi'):
>>> + return "scsi"
>>> + else:
>>> + return "ide"
>>> +
>>> +
>>> + def add_file_drive(vm, driver=get_device_driver(),
>>> host_file=None):
>>> + """
>>> + Hot-add a drive based on file to a vm
>>> + @param vm: Desired VM
>>> + @param driver: which driver should be used (default: same as
>>> in test)
>>> + @param host_file: Which file on host is the image (default:
>>> create new)
>>> + @return: Tupple(ret_file, device)
>>> + ret_file: created file handler (None if not
>>> created)
>>> + device: PCI id of the virtual disk
>>> + """
>>> + if not host_file:
>>> + host_file =
>>> tempfile.NamedTemporaryFile(prefix="cgroup-disk-",
>>> + suffix=".iso")
>>> + utils.system("dd if=/dev/zero of=%s bs=1M count=8
>>> &>/dev/null"
>>> + % (host_file.name))
>>> + ret_file = host_file
>>> + else:
>>> + ret_file = None
>>> +
>>> + out = vm.monitor.cmd("pci_add auto storage
>>> file=%s,if=%s,snapshot=off,"
>>> + "cache=off" % (host_file.name, driver))
>>> + dev = re.search(r'OK domain (\d+), bus (\d+), slot (\d+),
>>> function \d+',
>>> + out)
>>> + if not dev:
>>> + raise error.TestFail("Can't add device(%s, %s, %s): %s"
>>> % (vm,
>>> + host_file.name,
>>> driver, out))
>>> + device = "%s:%s:%s" % dev.groups()
>>> + return (ret_file, device)
>>> +
>>> +
>>> + def add_scsi_drive(vm, driver=get_device_driver(),
>>> host_file=None):
>>> + """
>>> + Hot-add a drive based on scsi_debug device to a vm
>>> + @param vm: Desired VM
>>> + @param driver: which driver should be used (default: same as
>>> in test)
>>> + @param host_file: Which dev on host is the image (default:
>>> create new)
>>> + @return: Tupple(ret_file, device)
>>> + ret_file: string of the created dev (None if not
>>> created)
>>> + device: PCI id of the virtual disk
>>> + """
>>> + if not host_file:
>>> + if utils.system_output("lsmod | grep scsi_debug -c") ==
>>> 0:
>>> + utils.system("modprobe scsi_debug dev_size_mb=8
>>> add_host=0")
>>> + utils.system("echo 1>
>>> /sys/bus/pseudo/drivers/scsi_debug/add_host")
>>> + host_file = utils.system_output("ls /dev/sd* | tail -n
>>> 1")
>>> + # Enable idling in scsi_debug drive
>>> + utils.system("echo 1> /sys/block/%s/queue/rotational" %
>>> host_file)
>>> + ret_file = host_file
>>> + else:
>>> + # Don't remove this device during cleanup
>>> + # Reenable idling in scsi_debug drive (in case it's not)
>>> + utils.system("echo 1> /sys/block/%s/queue/rotational" %
>>> host_file)
>>> + ret_file = None
>>> +
>>> + out = vm.monitor.cmd("pci_add auto storage
>>> file=%s,if=%s,snapshot=off,"
>>> + "cache=off" % (host_file, driver))
>>> + dev = re.search(r'OK domain (\d+), bus (\d+), slot (\d+),
>>> function \d+',
>>> + out)
>>> + if not dev:
>>> + raise error.TestFail("Can't add device(%s, %s, %s): %s"
>>> % (vm,
>>> + host_file,
>>> driver, out))
>>> + device = "%s:%s:%s" % dev.groups()
>>> + return (ret_file, device)
>>> +
>>> +
>>> + def rm_drive(vm, host_file, device):
>>> + """
>>> + Remove drive from vm and device on disk
>>> + ! beware to remove scsi devices in reverse order !
>>> + """
>>> + vm.monitor.cmd("pci_del %s" % device)
>>> +
>>> + if isinstance(host_file, file): # file
>>> + host_file.close()
>>> + elif isinstance(host_file, str): # scsi device
>>> + utils.system("echo -1>
>>> /sys/bus/pseudo/drivers/scsi_debug/add_host")
>>> + else: # custom file, do nothing
>>> + pass
>>> +
>>> + def get_all_pids(ppid):
>>> + """
>>> + Get all PIDs of children/threads of parent ppid
>>> + param ppid: parent PID
>>> + return: list of PIDs of all children/threads of ppid
>>> + """
>>> + return (utils.system_output("ps -L --ppid=%d -o lwp" % ppid)
>>> +
>>> .split('\n')[1:])
>>> +
>>> # Tests
>>> class _TestBlkioBandwidth:
>>> """
>>> @@ -46,9 +148,8 @@ def run_cgroup(test, params, env):
>>> """
>>> err = ""
>>> try:
>>> - for i in range (2):
>>> - vms[i].monitor.cmd("pci_del %s" %
>>> self.devices[i])
>>> - self.files[i].close()
>>> + for i in range(1, -1, -1):
>>> + rm_drive(vms[i], self.files[i], self.devices[i])
>>> except Exception, failure_detail:
>>> err += "\nCan't remove PCI drive: %s" %
>>> failure_detail
>>> try:
>>> @@ -89,8 +190,7 @@ def run_cgroup(test, params, env):
>>> if blkio.set_cgroup(self.vms[i].get_shell_pid(),
>>> pwd[i]):
>>> raise error.TestError("Could not set cgroup")
>>> # Move all existing threads into cgroup
>>> - for tmp in utils.system_output("ps -L --ppid=%d -o
>>> lwp"
>>> - %
>>> self.vms[i].get_shell_pid()).split('\n')[1:]:
>>> + 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]):
>>> @@ -101,18 +201,9 @@ def run_cgroup(test, params, env):
>>> # Add dummy drives
>>> # TODO: implement also using QMP.
>>> for i in range(2):
>>> - self.files.append(tempfile.NamedTemporaryFile(
>>> - prefix="cgroup-disk-",
>>> - suffix=".iso"))
>>> - utils.system("dd if=/dev/zero of=%s bs=1M count=10
>>> &>/dev/null"
>>> - % (self.files[i].name))
>>> - out = vms[i].monitor.cmd("pci_add auto storage
>>> file=%s,"
>>> - "if=virtio,snapshot=off,cache=off"
>>> - % (self.files[i].name))
>>> - out = re.search(r'OK domain (\d+), bus (\d+), slot
>>> (\d+), '
>>> - 'function \d+', out).groups()
>>> - self.devices.append("%s:%s:%s" % out)
>>> -
>>> + (host_file, device) = add_file_drive(vms[i],
>>> "virtio")
>>> + self.files.append(host_file)
>>> + self.devices.append(device)
>>>
>>> def run(self):
>>> """
>>> --
>>> 1.7.6.2
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe kvm" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
Lucas
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [kvm-autotest] cgroup-kvm: Four new BlkioThrottle tests
2011-10-07 18:24 [kvm-autotest] cgroup-kvm: Four new BlkioThrottle tests Lukas Doktor
` (4 preceding siblings ...)
2011-10-07 18:43 ` [kvm-autotest] cgroup-kvm: Four new BlkioThrottle tests Lukáš Doktor
@ 2011-10-11 20:30 ` Lucas Meneghel Rodrigues
5 siblings, 0 replies; 10+ messages in thread
From: Lucas Meneghel Rodrigues @ 2011-10-11 20:30 UTC (permalink / raw)
To: Lukas Doktor; +Cc: autotest, kvm-autotest, kvm
On 10/07/2011 03:24 PM, Lukas Doktor wrote:
> This is a patchset with four new tests to KVM specific cgroup testing. Also I made some modifications into (general) cgroup_common library which makes cgroup testing better readable and more safe to execute. Please find the details in each patch.
>
> Also please beware of qemu-kvm bugs which occurred for me (qemu-kvm 0.15.0 F17) which led to qemu SEGFAULTS or even to dysfunction (qemu-kvm 0.14 F15). I'll fill in Bugzilla on Monday.
>
> This was also sent as a github pull request, so if you feel like commenting on the pull request, be my guest:
> https://github.com/autotest/autotest/pull/33
Made comments on the pull request, please look at them and give the
patches a re-spin.
Thanks!
Lucas
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-10-11 20:30 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-07 18:24 [kvm-autotest] cgroup-kvm: Four new BlkioThrottle tests Lukas Doktor
2011-10-07 18:24 ` [PATCH 1/4] [kvm-autotest] cgroup-kvm: add_*_drive / rm_drive Lukas Doktor
2011-10-10 10:26 ` Jiri Zupka
2011-10-10 10:37 ` Lukáš Doktor
2011-10-11 17:13 ` Lucas Meneghel Rodrigues
2011-10-07 18:24 ` [PATCH 2/4] [autotest] cgroup: cleanup and structural changes Lukas Doktor
2011-10-07 18:24 ` [PATCH 3/4] [autotest] cgroup: {set,get}_property functions unification, bugfixies Lukas Doktor
2011-10-07 18:24 ` [PATCH 4/4] [kvm-autotest] cgroup-kvm: New subtest: TestBlkioThrottle* Lukas Doktor
2011-10-07 18:43 ` [kvm-autotest] cgroup-kvm: Four new BlkioThrottle tests Lukáš Doktor
2011-10-11 20:30 ` Lucas Meneghel Rodrigues
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).