198 lines
6.8 KiB
Python
198 lines
6.8 KiB
Python
import os, string, logging, re, random, shutil
|
|
from autotest_lib.client.bin import test, os_dep, utils
|
|
from autotest_lib.client.common_lib import error
|
|
|
|
|
|
def find_mnt_pt(path):
|
|
"""
|
|
Find on which mount point a given path is mounted.
|
|
|
|
@param path: Path we want to figure its mount point.
|
|
"""
|
|
pth = os.path.abspath(path)
|
|
while not os.path.ismount(pth):
|
|
pth = os.path.dirname(pth)
|
|
return pth
|
|
|
|
|
|
class ffsb(test.test):
|
|
"""
|
|
This class wraps FFSB (Flexible File System Benchmark) execution
|
|
under autotest.
|
|
|
|
@author Onkar N Mahajan (onkar.n.mahajan@linux.vnet.ibm.com)
|
|
"""
|
|
version = 1
|
|
params = {}
|
|
tempdirs = []
|
|
bytes = {'K':1024 , 'k':1024,
|
|
'M':1048576, 'm':1048576,
|
|
'G':1073741824, 'g':1073741824,
|
|
'T':1099511627776 , 't':1099511627776}
|
|
|
|
|
|
def initialize(self):
|
|
self.job.require_gcc()
|
|
self.results = []
|
|
self.nfail = 0
|
|
|
|
|
|
def set_ffsb_params(self, usrfl):
|
|
"""
|
|
This function checks for the user supplied FFSB profile file
|
|
and validates it against the availble resources on the
|
|
guest - currently only disk space validation is supported
|
|
but adjusting the number of threads according to the vcpus
|
|
exported by the qemu-kvm also needs to be added.
|
|
|
|
@param usrfl: Path to the user profile file.
|
|
"""
|
|
d = {}
|
|
fr = open(usrfl,'r')
|
|
for line in fr.read().split('\n'):
|
|
p = re.compile(r'\s*\t*\[{1}filesystem(\d+)\]{1}')
|
|
m = p.match(line)
|
|
if m:
|
|
fsno = int(line[m.start(1):m.end(1)])
|
|
d[fsno] = []
|
|
p = re.compile(r'(\s*\t*location)\=(.*)')
|
|
m = p.match(line)
|
|
if m:
|
|
path = line[m.start(2):m.end(2)]
|
|
mntpt = find_mnt_pt(path)
|
|
f = os.statvfs(mntpt)
|
|
avl_dsk_spc = f.f_bfree * f.f_bsize
|
|
avl_dsk_spc *= 0.95
|
|
d[fsno].append(mntpt)
|
|
d[fsno].append(int(avl_dsk_spc))
|
|
p = re.compile(r'(\s*\t*num_files)\=(\d+)')
|
|
|
|
m = p.match(line)
|
|
if m:
|
|
usrnumfl = int(line[m.start(2):m.end(2)])
|
|
d[fsno].append(usrnumfl)
|
|
p = re.compile(r'(\s*\t*max_filesize)\=(\d+[kKMmGgTt]?)')
|
|
m = p.match(line)
|
|
if m:
|
|
usrmaxflsz = line[m.start(2):m.end(2)]
|
|
usrmaxflsz = int(usrmaxflsz[0:-1]) * self.bytes[usrmaxflsz[-1]]
|
|
d[fsno].append(usrmaxflsz)
|
|
for k in d.keys():
|
|
while d[k][2]*d[k][3] >= d[k][1]:
|
|
d[k][2] -= 1
|
|
if d[k][2] == 0:
|
|
d[k][2] = 1
|
|
d[k][3] = d[k][1]
|
|
# If the ffsb mount point is on the same file system
|
|
# then use the available disk space after the previous
|
|
# tests
|
|
for k1 in d.keys():
|
|
if d[k1][0] == d[k][0]:
|
|
d[k1][1] -= (d[k][2]*d[k][3])
|
|
fr.close()
|
|
return d
|
|
|
|
|
|
def dup_ffsb_profilefl(self):
|
|
"""
|
|
Validates the path from the FFSB configuration file, the
|
|
disk space available for the test, warn the user and
|
|
change the file sizes and/or number of files to be used for
|
|
generating the workload according to the available disk space
|
|
on the guest.
|
|
"""
|
|
self.usrfl = '%s/%s' % (os.path.split(self.srcdir)[0],'profile.cfg')
|
|
self.sysfl = '%s/%s' % (self.srcdir,'profile.cfg')
|
|
|
|
params = self.set_ffsb_params(self.usrfl)
|
|
|
|
fsno = 0
|
|
fr = open(self.usrfl,'r')
|
|
fw = open(self.sysfl,'w')
|
|
for line in fr.read().split('\n'):
|
|
p = re.compile(r'\s*\t*\[{1}filesystem(\d+)\]{1}')
|
|
m = p.match(line)
|
|
if m:
|
|
fsno = int(line[m.start(1):m.end(1)])
|
|
p = re.compile(r'(\s*\t*location)\=(.*)')
|
|
m = p.match(line)
|
|
if m:
|
|
while True:
|
|
dirnm = ''.join(random.choice(string.letters) for i in xrange(9))
|
|
if line[m.end(2) - 1] == '/':
|
|
newline = '%s%s' % (line[0:m.end(2)], dirnm)
|
|
ffsbdir = '%s%s' % (line[m.start(2):m.end(2)], dirnm)
|
|
else:
|
|
newline = '%s/%s' % (line[0:m.end(2)], dirnm)
|
|
ffsbdir = '%s/%s' % (line[m.start(2):m.end(2)], dirnm)
|
|
self.tempdirs.append(ffsbdir)
|
|
if os.path.exists(ffsbdir):
|
|
continue
|
|
else:
|
|
os.makedirs(ffsbdir)
|
|
break
|
|
fw.write(newline+'\n')
|
|
continue
|
|
p = re.compile(r'(\s*\t*num_files)\=(.*)')
|
|
m = p.match(line)
|
|
if m:
|
|
newline = '%s=%s' % (line[0:m.end(1)], str(params[fsno][2]))
|
|
fw.write(newline+'\n')
|
|
continue
|
|
p = re.compile(r'(\s*\t*max_filesize)\=(\d+[kKMmGgTt]?)')
|
|
m = p.match(line)
|
|
if m:
|
|
newline = '%s%s' % (line[0:m.start(2)], str(params[fsno][3]))
|
|
fw.write(newline+'\n')
|
|
continue
|
|
fw.write(line+'\n')
|
|
fr.close()
|
|
fw.close()
|
|
|
|
|
|
def setup(self, tarball='ffsb-6.0-rc2.tar.bz2'):
|
|
"""
|
|
Uncompress the FFSB tarball and compiles it.
|
|
|
|
@param tarball: FFSB tarball. Could be either a path relative to
|
|
self.srcdir or a URL.
|
|
"""
|
|
tarball = utils.unmap_url(self.bindir, tarball, self.tmpdir)
|
|
utils.extract_tarball_to_dir(tarball, self.srcdir)
|
|
os.chdir(self.srcdir)
|
|
os_dep.command('gcc')
|
|
utils.configure()
|
|
utils.make()
|
|
|
|
|
|
def run_once(self):
|
|
"""
|
|
Runs a single iteration of the FFSB.
|
|
"""
|
|
self.dup_ffsb_profilefl()
|
|
# Run FFSB using abspath
|
|
cmd = '%s/ffsb %s/profile.cfg' % (self.srcdir, self.srcdir)
|
|
logging.info("FFSB command: %s", cmd)
|
|
self.results_path = os.path.join(self.resultsdir,
|
|
'raw_output_%s' % self.iteration)
|
|
try:
|
|
self.results = utils.system_output(cmd, retain_output=True)
|
|
logging.info(self.results)
|
|
utils.open_write_close(self.results_path, self.results)
|
|
except error.CmdError, e:
|
|
self.nfail += 1
|
|
logging.error('Failed to execute FFSB : %s', e)
|
|
|
|
|
|
def postprocess(self):
|
|
"""
|
|
Do test postprocessing. Fail the test or clean up results.
|
|
"""
|
|
if self.nfail != 0:
|
|
raise error.TestError('FFSB test failed.')
|
|
else:
|
|
logging.info('FFSB test passed')
|
|
logging.info('Cleaning up test data...')
|
|
for l in self.tempdirs:
|
|
shutil.rmtree(l)
|