def run_once(self): errors = 0 # The minimum available space we expect on temp filesystems. # TempFS allows 1/2 of Total Memory for each temp fs. Our threshold # allows for 50% usage of space allocated before this test is run. threshold = utils.memtotal()/4 tempdirs = ['/dev', '/tmp', '/dev/shm', '/var/tmp', '/run', '/run/lock'] for dir in tempdirs: if os.path.isdir(dir): # utils.freespace is in bytes, so convert to kb. avail = utils.freespace(dir)/1024 if avail < threshold: logging.error('Not enough available space on %s', dir) logging.error('%d bytes is minimum, found %d bytes', (threshold, avail)) errors += 1 else: logging.error('%s does not exist!' % dir) errors += 1 if errors: raise error.TestFail('There were %d temp directory errors' % errors)
def execute(self, disks = None, gigabytes = None, chunk_mb = utils.memtotal() / 1024): os.chdir(self.srcdir) if not disks: disks = [self.tmpdir] if not gigabytes: free = 100 # cap it at 100GB by default for disk in disks: free = min(utils.freespace(disk) / 1024**3, free) gigabytes = free logging.info("resizing to %s GB", gigabytes) sys.stdout.flush() self.chunk_mb = chunk_mb self.memory_mb = utils.memtotal()/1024 if self.memory_mb > chunk_mb: e_msg = "Too much RAM (%dMB) for this test to work" % self.memory_mb raise error.TestError(e_msg) chunks = (1024 * gigabytes) / chunk_mb for i in range(chunks): pids = [] for disk in disks: pid = self.test_one_disk_chunk(disk, i) pids.append(pid) errors = [] for pid in pids: (junk, retval) = os.waitpid(pid, 0) if (retval != 0): errors.append(retval) if errors: raise error.TestError("Errors from children: %s" % errors)
def run_once(self, disks=None, gigabytes=None, chunk_mb=None): """ Runs one iteration of disktest. @param disks: List of directories (usually mountpoints) to be passed to the test. @param gigabytes: Disk space that will be used for the test to run. @param chunk_mb: Size of the portion of the disk used to run the test. Cannot be larger than the total amount of free RAM. """ os.chdir(self.srcdir) if chunk_mb is None: chunk_mb = utils.memtotal() / 1024 if disks is None: disks = [self.tmpdir] if gigabytes is None: free = 100 # cap it at 100GB by default for disk in disks: free = min(utils.freespace(disk) / 1024**3, free) gigabytes = free logging.info("Resizing to %s GB", gigabytes) sys.stdout.flush() self.chunk_mb = chunk_mb self.memory_mb = utils.memtotal()/1024 if self.memory_mb > chunk_mb: raise error.TestError("Too much RAM (%dMB) for this test to work" % self.memory_mb) chunks = (1024 * gigabytes) / chunk_mb logging.info("Total of disk chunks that will be used: %s", chunks) for i in range(chunks): pids = [] for disk in disks: pid = self.test_one_disk_chunk(disk, i) pids.append(pid) errors = [] for pid in pids: (junk, retval) = os.waitpid(pid, 0) if (retval != 0): errors.append(retval) if errors: raise error.TestError("Errors from children: %s" % errors)
def run_once(self, args = '', stress_length=60): if not args: # We will use 2 workers of each type for each CPU detected threads = 2 * utils.count_cpus() # Sometimes the default memory used by each memory worker (256 M) # might make our machine go OOM and then funny things might start to # happen. Let's avoid that. mb = utils.freememtotal() + utils.read_from_meminfo('SwapFree') / 2 memory_per_thread = (mb * 1024) / threads # Even though unlikely, it's good to prevent from allocating more # disk than this machine actually has on its autotest directory # (limit the amount of disk used to max of 90 % of free space) free_disk = utils.freespace(self.srcdir) file_size_per_thread = 1024 ** 2 if (0.9 * free_disk) < file_size_per_thread * threads: file_size_per_thread = (0.9 * free_disk) / threads # Number of CPU workers spinning on sqrt() args = '--cpu %d ' % threads # Number of IO workers spinning on sync() args += '--io %d ' % threads # Number of Memory workers spinning on malloc()/free() args += '--vm %d ' % threads # Amount of memory used per each worker args += '--vm-bytes %d ' % memory_per_thread # Number of HD workers spinning on write()/ulink() args += '--hdd %d ' % threads # Size of the files created by each worker in bytes args += '--hdd-bytes %d ' % file_size_per_thread # Time for which the stress test will run args += '--timeout %d ' % stress_length # Verbose flag args += '--verbose' utils.system(self.srcdir + '/src/stress ' + args)
def run_once(self, args='', stress_length=60): if not args: # We will use 2 workers of each type for each CPU detected threads = 2 * utils.count_cpus() # Sometimes the default memory used by each memory worker (256 M) # might make our machine go OOM and then funny things might start to # happen. Let's avoid that. mb = utils.freememtotal() + utils.read_from_meminfo('SwapFree') / 2 memory_per_thread = (mb * 1024) / threads # Even though unlikely, it's good to prevent from allocating more # disk than this machine actually has on its autotest directory # (limit the amount of disk used to max of 90 % of free space) free_disk = utils.freespace(self.srcdir) file_size_per_thread = 1024**2 if (0.9 * free_disk) < file_size_per_thread * threads: file_size_per_thread = (0.9 * free_disk) / threads # Number of CPU workers spinning on sqrt() args = '--cpu %d ' % threads # Number of IO workers spinning on sync() args += '--io %d ' % threads # Number of Memory workers spinning on malloc()/free() args += '--vm %d ' % threads # Amount of memory used per each worker args += '--vm-bytes %d ' % memory_per_thread # Number of HD workers spinning on write()/ulink() args += '--hdd %d ' % threads # Size of the files created by each worker in bytes args += '--hdd-bytes %d ' % file_size_per_thread # Time for which the stress test will run args += '--timeout %d ' % stress_length # Verbose flag args += '--verbose' utils.system(self.srcdir + '/src/stress ' + args)
def stop(self): # if no maximum usage rate was set, we don't need to # generate any warnings if not self.max_mb_per_hour: return final_space = utils.freespace(self.device) used_space = self.initial_space - final_space stop_time = time.time() total_time = stop_time - self.start_time # round up the time to one minute, to keep extremely short # tests from generating false positives due to short, badly # timed bursts of activity total_time = max(total_time, 60.0) # determine the usage rate bytes_per_sec = used_space / total_time mb_per_sec = bytes_per_sec / 1024**2 mb_per_hour = mb_per_sec * 60 * 60 if mb_per_hour > self.max_mb_per_hour: msg = ("disk space on %s was consumed at a rate of %.2f MB/hour") msg %= (self.device, mb_per_hour) self.func(msg)
def backup_image(params, root_dir, action, good=True): """ Backup or restore a disk image, depending on the action chosen. @param params: Dictionary containing the test parameters. @param root_dir: Base directory for relative filenames. @param action: Whether we want to backup or restore the image. @param good: If we are backing up a good image(we want to restore it) or a bad image (we are saving a bad image for posterior analysis). @note: params should contain: image_name -- the name of the image file, without extension image_format -- the format of the image (qcow2, raw etc) """ def backup_raw_device(src, dst): utils.system("dd if=%s of=%s bs=4k conv=sync" % (src, dst)) def backup_image_file(src, dst): logging.debug("Copying %s -> %s", src, dst) shutil.copy(src, dst) def get_backup_name(filename, backup_dir, good): if not os.path.isdir(backup_dir): os.makedirs(backup_dir) basename = os.path.basename(filename) if good: backup_filename = "%s.backup" % basename else: backup_filename = ( "%s.bad.%s" % (basename, virt_utils.generate_random_string(4))) return os.path.join(backup_dir, backup_filename) image_filename = get_image_filename(params, root_dir) backup_dir = params.get("backup_dir") if params.get('image_raw_device') == 'yes': iname = "raw_device" iformat = params.get("image_format", "qcow2") ifilename = "%s.%s" % (iname, iformat) ifilename = virt_utils.get_path(root_dir, ifilename) image_filename_backup = get_backup_name(ifilename, backup_dir, good) backup_func = backup_raw_device else: image_filename_backup = get_backup_name(image_filename, backup_dir, good) backup_func = backup_image_file if action == 'backup': image_dir = os.path.dirname(image_filename) image_dir_disk_free = utils.freespace(image_dir) image_filename_size = os.path.getsize(image_filename) image_filename_backup_size = 0 if os.path.isfile(image_filename_backup): image_filename_backup_size = os.path.getsize(image_filename_backup) disk_free = image_dir_disk_free + image_filename_backup_size minimum_disk_free = 1.2 * image_filename_size if disk_free < minimum_disk_free: image_dir_disk_free_gb = float(image_dir_disk_free) / 10**9 minimum_disk_free_gb = float(minimum_disk_free) / 10**9 logging.error( "Dir %s has %.1f GB free, less than the minimum " "required to store a backup, defined to be 120%% " "of the backup size, %.1f GB. Skipping backup...", image_dir, image_dir_disk_free_gb, minimum_disk_free_gb) return if good: # In case of qemu-img check return 1, we will make 2 backups, one # for investigation and other, to use as a 'pristine' image for # further tests state = 'good' else: state = 'bad' logging.info("Backing up %s image file %s", state, image_filename) src, dst = image_filename, image_filename_backup elif action == 'restore': if not os.path.isfile(image_filename_backup): logging.error('Image backup %s not found, skipping restore...', image_filename_backup) return logging.info("Restoring image file %s from backup", image_filename) src, dst = image_filename_backup, image_filename backup_func(src, dst)
def start(self): self.initial_space = utils.freespace(self.device) self.start_time = time.time()
def backup_image(params, root_dir, action, good=True): """ Backup or restore a disk image, depending on the action chosen. @param params: Dictionary containing the test parameters. @param root_dir: Base directory for relative filenames. @param action: Whether we want to backup or restore the image. @param good: If we are backing up a good image(we want to restore it) or a bad image (we are saving a bad image for posterior analysis). @note: params should contain: image_name -- the name of the image file, without extension image_format -- the format of the image (qcow2, raw etc) """ def backup_raw_device(src, dst): utils.system("dd if=%s of=%s bs=4k conv=sync" % (src, dst)) def backup_image_file(src, dst): logging.debug("Copying %s -> %s", src, dst) shutil.copy(src, dst) def get_backup_name(filename, backup_dir, good): if not os.path.isdir(backup_dir): os.makedirs(backup_dir) basename = os.path.basename(filename) if good: backup_filename = "%s.backup" % basename else: backup_filename = ("%s.bad.%s" % (basename, virt_utils.generate_random_string(4))) return os.path.join(backup_dir, backup_filename) image_filename = get_image_filename(params, root_dir) backup_dir = params.get("backup_dir") if params.get('image_raw_device') == 'yes': iname = "raw_device" iformat = params.get("image_format", "qcow2") ifilename = "%s.%s" % (iname, iformat) ifilename = virt_utils.get_path(root_dir, ifilename) image_filename_backup = get_backup_name(ifilename, backup_dir, good) backup_func = backup_raw_device else: image_filename_backup = get_backup_name(image_filename, backup_dir, good) backup_func = backup_image_file if action == 'backup': image_dir = os.path.dirname(image_filename) image_dir_disk_free = utils.freespace(image_dir) image_filename_size = os.path.getsize(image_filename) image_filename_backup_size = 0 if os.path.isfile(image_filename_backup): image_filename_backup_size = os.path.getsize(image_filename_backup) disk_free = image_dir_disk_free + image_filename_backup_size minimum_disk_free = 1.2 * image_filename_size if disk_free < minimum_disk_free: image_dir_disk_free_gb = float(image_dir_disk_free) / 10**9 minimum_disk_free_gb = float(minimum_disk_free) / 10**9 logging.error("Dir %s has %.1f GB free, less than the minimum " "required to store a backup, defined to be 120%% " "of the backup size, %.1f GB. Skipping backup...", image_dir, image_dir_disk_free_gb, minimum_disk_free_gb) return if good: # In case of qemu-img check return 1, we will make 2 backups, one # for investigation and other, to use as a 'pristine' image for # further tests state = 'good' else: state = 'bad' logging.info("Backing up %s image file %s", state, image_filename) src, dst = image_filename, image_filename_backup elif action == 'restore': if not os.path.isfile(image_filename_backup): logging.error('Image backup %s not found, skipping restore...', image_filename_backup) return logging.info("Restoring image file %s from backup", image_filename) src, dst = image_filename_backup, image_filename backup_func(src, dst)