Home | History | Annotate | Download | only in ffsb
      1 import os, string, logging, re, random, shutil
      2 from autotest_lib.client.bin import test, os_dep, utils
      3 from autotest_lib.client.common_lib import error
      4 
      5 
      6 def find_mnt_pt(path):
      7     """
      8     Find on which mount point a given path is mounted.
      9 
     10     @param path: Path we want to figure its mount point.
     11     """
     12     pth = os.path.abspath(path)
     13     while not os.path.ismount(pth):
     14         pth = os.path.dirname(pth)
     15     return pth
     16 
     17 
     18 class ffsb(test.test):
     19     """
     20     This class wraps FFSB (Flexible File System Benchmark) execution
     21     under autotest.
     22 
     23     @author Onkar N Mahajan (onkar.n.mahajan (at] linux.vnet.ibm.com)
     24     """
     25     version = 1
     26     params = {}
     27     tempdirs = []
     28     bytes = {'K':1024 , 'k':1024,
     29              'M':1048576, 'm':1048576,
     30              'G':1073741824, 'g':1073741824,
     31              'T':1099511627776 , 't':1099511627776}
     32 
     33 
     34     def initialize(self):
     35         self.job.require_gcc()
     36         self.results = []
     37         self.nfail = 0
     38 
     39 
     40     def set_ffsb_params(self, usrfl):
     41         """
     42         This function checks for the user supplied FFSB profile file
     43         and validates it against the availble resources on the
     44         guest - currently only disk space validation is supported
     45         but adjusting the number of threads according to the vcpus
     46         exported by the qemu-kvm also needs to be added.
     47 
     48         @param usrfl: Path to the user profile file.
     49         """
     50         d = {}
     51         fr = open(usrfl,'r')
     52         for line in fr.read().split('\n'):
     53             p = re.compile(r'\s*\t*\[{1}filesystem(\d+)\]{1}')
     54             m = p.match(line)
     55             if m:
     56                 fsno = int(line[m.start(1):m.end(1)])
     57                 d[fsno] = []
     58             p = re.compile(r'(\s*\t*location)\=(.*)')
     59             m = p.match(line)
     60             if m:
     61                 path = line[m.start(2):m.end(2)]
     62                 mntpt = find_mnt_pt(path)
     63                 f = os.statvfs(mntpt)
     64                 avl_dsk_spc = f.f_bfree * f.f_bsize
     65                 avl_dsk_spc *= 0.95
     66                 d[fsno].append(mntpt)
     67                 d[fsno].append(int(avl_dsk_spc))
     68             p = re.compile(r'(\s*\t*num_files)\=(\d+)')
     69 
     70             m = p.match(line)
     71             if m:
     72                 usrnumfl = int(line[m.start(2):m.end(2)])
     73                 d[fsno].append(usrnumfl)
     74             p = re.compile(r'(\s*\t*max_filesize)\=(\d+[kKMmGgTt]?)')
     75             m = p.match(line)
     76             if m:
     77                 usrmaxflsz = line[m.start(2):m.end(2)]
     78                 usrmaxflsz = int(usrmaxflsz[0:-1]) * self.bytes[usrmaxflsz[-1]]
     79                 d[fsno].append(usrmaxflsz)
     80         for k in d.keys():
     81             while d[k][2]*d[k][3] >= d[k][1]:
     82                 d[k][2] -= 1
     83             if d[k][2] == 0:
     84                 d[k][2] = 1
     85                 d[k][3] = d[k][1]
     86             # If the ffsb mount point is on the same file system
     87             # then use the available disk space after the previous
     88             # tests
     89             for k1 in d.keys():
     90                 if d[k1][0] == d[k][0]:
     91                     d[k1][1] -= (d[k][2]*d[k][3])
     92         fr.close()
     93         return d
     94 
     95 
     96     def dup_ffsb_profilefl(self):
     97         """
     98         Validates the path from the FFSB configuration file, the
     99         disk space available for the test, warn the user and
    100         change the file sizes and/or number of files to be used for
    101         generating the workload according to the available disk space
    102         on the guest.
    103         """
    104         self.usrfl = '%s/%s' % (os.path.split(self.srcdir)[0],'profile.cfg')
    105         self.sysfl = '%s/%s' % (self.srcdir,'profile.cfg')
    106 
    107         params = self.set_ffsb_params(self.usrfl)
    108 
    109         fsno = 0
    110         fr = open(self.usrfl,'r')
    111         fw = open(self.sysfl,'w')
    112         for line in fr.read().split('\n'):
    113             p = re.compile(r'\s*\t*\[{1}filesystem(\d+)\]{1}')
    114             m = p.match(line)
    115             if m:
    116                 fsno = int(line[m.start(1):m.end(1)])
    117             p = re.compile(r'(\s*\t*location)\=(.*)')
    118             m = p.match(line)
    119             if m:
    120                 while True:
    121                     dirnm = ''.join(random.choice(string.letters) for i in xrange(9))
    122                     if line[m.end(2) - 1] == '/':
    123                         newline = '%s%s' % (line[0:m.end(2)], dirnm)
    124                         ffsbdir = '%s%s' % (line[m.start(2):m.end(2)], dirnm)
    125                     else:
    126                         newline = '%s/%s' % (line[0:m.end(2)], dirnm)
    127                         ffsbdir = '%s/%s' % (line[m.start(2):m.end(2)], dirnm)
    128                     self.tempdirs.append(ffsbdir)
    129                     if os.path.exists(ffsbdir):
    130                         continue
    131                     else:
    132                         os.makedirs(ffsbdir)
    133                         break
    134                 fw.write(newline+'\n')
    135                 continue
    136             p = re.compile(r'(\s*\t*num_files)\=(.*)')
    137             m = p.match(line)
    138             if m:
    139                 newline = '%s=%s' % (line[0:m.end(1)], str(params[fsno][2]))
    140                 fw.write(newline+'\n')
    141                 continue
    142             p = re.compile(r'(\s*\t*max_filesize)\=(\d+[kKMmGgTt]?)')
    143             m = p.match(line)
    144             if m:
    145                 newline = '%s%s' % (line[0:m.start(2)], str(params[fsno][3]))
    146                 fw.write(newline+'\n')
    147                 continue
    148             fw.write(line+'\n')
    149         fr.close()
    150         fw.close()
    151 
    152 
    153     def setup(self, tarball='ffsb-6.0-rc2.tar.bz2'):
    154         """
    155         Uncompress the FFSB tarball and compiles it.
    156 
    157         @param tarball: FFSB tarball. Could be either a path relative to
    158                 self.srcdir or a URL.
    159         """
    160         tarball = utils.unmap_url(self.bindir, tarball, self.tmpdir)
    161         utils.extract_tarball_to_dir(tarball, self.srcdir)
    162         os.chdir(self.srcdir)
    163         os_dep.command('gcc')
    164         utils.configure()
    165         utils.make()
    166 
    167 
    168     def run_once(self):
    169         """
    170         Runs a single iteration of the FFSB.
    171         """
    172         self.dup_ffsb_profilefl()
    173         # Run FFSB using abspath
    174         cmd = '%s/ffsb %s/profile.cfg' % (self.srcdir, self.srcdir)
    175         logging.info("FFSB command: %s", cmd)
    176         self.results_path = os.path.join(self.resultsdir,
    177                                          'raw_output_%s' % self.iteration)
    178         try:
    179             self.results = utils.system_output(cmd, retain_output=True)
    180             logging.info(self.results)
    181             utils.open_write_close(self.results_path, self.results)
    182         except error.CmdError, e:
    183             self.nfail += 1
    184             logging.error('Failed to execute FFSB : %s', e)
    185 
    186 
    187     def postprocess(self):
    188         """
    189         Do test postprocessing. Fail the test or clean up results.
    190         """
    191         if self.nfail != 0:
    192             raise error.TestError('FFSB test failed.')
    193         else:
    194             logging.info('FFSB test passed')
    195             logging.info('Cleaning up test data...')
    196             for l in self.tempdirs:
    197                 shutil.rmtree(l)
    198