commit 0a32526dfcc17f70db2e9d72b98c4bca80e31d58
Author: David Sorber <dsorber@ryft.com>
Date:   Tue Nov 25 13:22:32 2014 -0500

    Created a top level script for fully automating the full extent test process (well, aside from data analysis).

diff --git a/software/fiemap_testing/extent_test.py b/software/fiemap_testing/extent_test.py
new file mode 100644
index 0000000..844c9f8
--- /dev/null
+++ b/software/fiemap_testing/extent_test.py
@@ -0,0 +1,164 @@
+from multiprocessing import Process
+import datetime
+import os
+import subprocess
+import sys
+
+devices = {'/dev/sdb1': {'mount': '/mnt/smc0', 'size': 64},
+           '/dev/sdc1': {'mount': '/mnt/smc1', 'size': 256},
+           '/dev/sdd1': {'mount': '/mnt/smc2', 'size': 1024}}
+
+MIN_FILE_SIZE =  10240 # in megabytes
+MAX_FILE_SIZE = 102400 # in megabytes
+DRIVE_CAPACITY = int(1.8 * (2**20)) # in megabytes
+
+class Tester(Process):
+    """
+    """
+    
+    def __init__(self, device, mount_path, chunk_size, fs_name, output_path):
+        Process.__init__(self)
+        self.device = device
+        self.mount_path = mount_path
+        self.chunk_size = chunk_size
+        self.mkfs_cmd = '/sbin/mkfs.{:s}'.format(fs_name)
+        self.output_path = output_path
+                
+        # Build a logfile name for the stdout and stderr of the subprocess calls
+        logname = 'subproc_{:d}.log'.format(self.chunk_size)
+        self.subproclog = open(os.path.join(self.output_path, logname), 'w')
+        
+    def out(self, msg):
+        print '[{:4d}] {:s}'.format(self.chunk_size, msg)
+        sys.stdout.flush()
+        
+    def cmd(self, cmd):
+        return subprocess.call(cmd, shell=True, stdout=self.subproclog, 
+                               stderr=self.subproclog)
+        
+    def run(self):
+        self.out('Started')
+        
+        # Unmount mount path
+        cmd = 'umount {:s}'.format(self.mount_path)
+        rc = self.cmd(cmd)
+        if rc == 0:
+            self.out('Unmounted {:s}'.format(self.mount_path))
+        elif rc == 2:
+            self.out('{:s} was not mounted'.format(self.mount_path))
+        else:
+            self.out('Error unmounting {:s}'.format(self.mount_path))
+            
+        # Format device partition
+        cmd = '{:s} -f {:s}'.format(self.mkfs_cmd, self.device)
+        rc = self.cmd(cmd)
+        if rc == 0:
+            self.out('Formatted {:s}'.format(self.device))
+        else:
+            self.out('Error while formatting {:s}'.format(self.device))
+            
+        # Mount path
+        cmd = 'mount {:s} {:s}'.format(self.device, self.mount_path)
+        rc = self.cmd(cmd)
+        if rc == 0:
+            self.out('Mounted {:s} on {:s}'.format(self.device, self.mount_path))
+        else:
+            self.out('Error mounting {:s} on {:s}'.format(self.device, self.mount_path))
+            
+        # Run filler script        
+        output_file = os.path.join(self.output_path, 
+                                   'extent_test_{:d}MB.log'.format(self.chunk_size))
+                                   
+        min_chunks = MIN_FILE_SIZE / self.chunk_size
+        max_chunks = MAX_FILE_SIZE / self.chunk_size
+        
+        cmd_args = (self.mount_path, min_chunks, max_chunks, self.chunk_size, 
+                    DRIVE_CAPACITY,  output_file)        
+        cmd = 'python filler.py {:s} {:d} {:d} {:d} {:d} > {:s}'.format(*cmd_args)
+        
+        self.out('Started filler.py on {:s}'.format(self.mount_path))
+        start = datetime.datetime.now()
+        rc = self.cmd(cmd)
+        if rc == 0:
+            self.out('filler.py complete on {:s}'.format(self.mount_path))
+        end = datetime.datetime.now()
+        
+        # Display elapsed time for filler.py script
+        elpased = end - start
+        hours, remainder = divmod(elpased.seconds, 3600)
+        minutes, seconds = divmod(remainder, 60)
+        time = '{:02d}:{:02d}:{:02d}'.format(hours, minutes, seconds)
+        self.out('Filler took: {:s}'.format(time))
+        
+        # Run analyze.py script
+        output_file = os.path.join(self.output_path, 
+                                   'extent_analysis_{:d}MB.log'.format(self.chunk_size))
+        cmd_args = (self.mount_path, output_file)
+        cmd = 'python analyze.py {:s} > {:s}'.format(*cmd_args)
+        rc = self.cmd(cmd)
+        self.out('Ran analyze.py on {:s}'.format(self.output_path))
+        
+        # Run raw_data.py script
+        output_file = os.path.join(self.output_path, 
+                                   'raw_extents_{:d}MB.log'.format(self.chunk_size))
+        cmd_args = (self.mount_path, output_file)
+        cmd = 'python raw_data.py {:s} > {:s}'.format(*cmd_args)
+        rc = self.cmd(cmd)
+        self.out('Ran raw_data.py on {:s}'.format(self.output_path))
+
+        # Close the subprocess output log for good measure
+        self.subproclog.close()
+
+def usage():
+    """ TODO: write usage blurb to be printed here
+    """
+    pass
+
+def main():
+    """
+    arg1 - file system name (e.g. xfs)
+    arg2 - path to location to store outputs
+    """
+        
+    if len(sys.argv) < 3:
+        print 'ERROR: not enough arguments provided'
+        return -1
+        
+    fs_name = sys.argv[1]
+    output_path = sys.argv[2]
+    
+    # Make sure file system name exists (i.e. /sbin/mkfs.[FSNAME] exists)
+    if not os.path.exists('/sbin/mkfs.{:s}'.format(fs_name)):
+        print 'ERROR: "{:s}" is not a known file system on this system!'.format(fs_name)
+        return -1
+    
+    # Make sure the output path exists
+    if not os.path.exists(output_path):
+        print 'ERROR: output path "{:s}" does not exist!'.format(output_path)
+        return -1
+        
+    # Create output folder if it does not already exist
+    output_path = os.path.join(output_path, fs_name)
+    if os.path.exists(output_path):
+        print 'ERROR: output folder "{:s}" already exists!'.format(output_path)
+        return -1
+    os.makedirs(output_path)
+    
+    # Create Tester instances for each of the devices
+    tester_workers = []
+    for device, dev_attrs in devices.iteritems():
+        tester_workers.append(Tester(device, dev_attrs['mount'],
+                              dev_attrs['size'], fs_name, output_path))
+    
+    # Start all Tester processes
+    for worker in tester_workers:
+        worker.start()
+    
+    # Join each of the processes
+    for worker in tester_workers:
+        worker.join()
+    
+    print 'Test complete'
+    
+if __name__ == '__main__':
+    sys.exit(main())
