|
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())
|