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.disk_srcdir)
        if chunk_mb is None:
            chunk_mb = utils_memory.memtotal() / 1024 / 8
        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_memory.memtotal() / 1024 / 8
        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, 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.disk_srcdir)
        if chunk_mb is None:
            chunk_mb = utils.memtotal() / 1024 / 8
        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 / 8
        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)
Beispiel #3
0
    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_memory.freememtotal() +
                  utils_memory.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)
Beispiel #4
0
    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_memory.freememtotal() +
                  utils_memory.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)
Beispiel #5
0
    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)
Beispiel #6
0
    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)
Beispiel #7
0
    def backup_image(self, params, root_dir, action, good=True,
                     skip_existing=False):
        """
        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):
            if os.path.exists(src):
                utils.system("dd if=%s of=%s bs=4k conv=sync" % (src, dst))
            else:
                logging.info("No source %s, skipping dd...", src)

        def backup_image_file(src, dst):
            logging.debug("Copying %s -> %s", src, dst)
            if os.path.isfile(dst) and os.path.isfile(src):
                os.unlink(dst)
            if os.path.isfile(src):
                shutil.copy(src, dst)
            else:
                logging.info("No source file %s, skipping copy...", src)

        def get_backup_set(filename, backup_dir, action, good):
            """
            Get all sources and destinations required for each backup.
            """
            if not os.path.isdir(backup_dir):
                os.makedirs(backup_dir)
            basename = os.path.basename(filename)
            bkp_set = []
            if good:
                src = filename
                dst = os.path.join(backup_dir, "%s.backup" % basename)
                if action == 'backup':
                    bkp_set = [[src, dst]]
                elif action == 'restore':
                    bkp_set = [[dst, src]]
            else:
                # We have to make 2 backups, one of the bad image, another one
                # of the good image
                src_bad = filename
                src_good = os.path.join(backup_dir, "%s.backup" % basename)
                hsh = utils_misc.generate_random_string(4)
                dst_bad = (os.path.join(backup_dir, "%s.bad.%s" %
                                        (basename, hsh)))
                dst_good = (os.path.join(backup_dir, "%s.good.%s" %
                                         (basename, hsh)))
                if action == 'backup':
                    bkp_set = [[src_bad, dst_bad], [src_good, dst_good]]
                elif action == 'restore':
                    bkp_set = [[src_good, src_bad]]

            if not bkp_set:
                logging.error("No backup sets for action: %s, state: %s",
                              action, good)

            return bkp_set

        image_filename = self.image_filename
        backup_dir = params.get("backup_dir", "")
        if not os.path.isabs(backup_dir):
            backup_dir = os.path.join(root_dir, backup_dir)
        if params.get('image_raw_device') == 'yes':
            iname = "raw_device"
            iformat = params.get("image_format", "qcow2")
            ifilename = "%s.%s" % (iname, iformat)
            ifilename = utils_misc.get_path(root_dir, ifilename)
            backup_set = get_backup_set(ifilename, backup_dir, action, good)
            backup_func = backup_raw_device
        else:
            backup_set = get_backup_set(image_filename, backup_dir, action,
                                        good)
            backup_func = backup_image_file

        if action == 'backup':
            image_dir = os.path.dirname(image_filename)
            image_dir_disk_free = utils.freespace(image_dir)

            backup_size = 0
            for src, dst in backup_set:
                if os.path.isfile(src):
                    backup_size += os.path.getsize(src)

            minimum_disk_free = 1.2 * backup_size
            if image_dir_disk_free < minimum_disk_free:
                image_dir_disk_free_gb = float(image_dir_disk_free) / 10 ** 9
                backup_size_gb = float(backup_size) / 10 ** 9
                minimum_disk_free_gb = float(minimum_disk_free) / 10 ** 9
                logging.error("Free space on %s: %.1f GB", image_dir,
                              image_dir_disk_free_gb)
                logging.error("Backup size: %.1f GB", backup_size_gb)
                logging.error("Minimum free space acceptable: %.1f GB",
                              minimum_disk_free_gb)
                logging.error("Available disk space is not sufficient for a"
                              "full backup. Skipping backup...")
                return

        for src, dst in backup_set:
            if action == 'backup' and skip_existing and os.path.exists(dst):
                continue
            backup_func(src, dst)
Beispiel #8
0
 def start(self):
     self.initial_space = utils.freespace(self.device)
     self.start_time = time.time()
Beispiel #9
0
    def backup_image(self,
                     params,
                     root_dir,
                     action,
                     good=True,
                     skip_existing=False):
        """
        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):
            if os.path.exists(src):
                utils.system("dd if=%s of=%s bs=4k conv=sync" % (src, dst))
            else:
                logging.info("No source %s, skipping dd...", src)

        def backup_image_file(src, dst):
            logging.debug("Copying %s -> %s", src, dst)
            if os.path.isfile(dst) and os.path.isfile(src):
                os.unlink(dst)
            if os.path.isfile(src):
                shutil.copy(src, dst)
            else:
                logging.info("No source file %s, skipping copy...", src)

        def get_backup_set(filename, backup_dir, action, good):
            """
            Get all sources and destinations required for each backup.
            """
            if not os.path.isdir(backup_dir):
                os.makedirs(backup_dir)
            basename = os.path.basename(filename)
            bkp_set = []
            if good:
                src = filename
                dst = os.path.join(backup_dir, "%s.backup" % basename)
                if action == 'backup':
                    bkp_set = [[src, dst]]
                elif action == 'restore':
                    bkp_set = [[dst, src]]
            else:
                # We have to make 2 backups, one of the bad image, another one
                # of the good image
                src_bad = filename
                src_good = os.path.join(backup_dir, "%s.backup" % basename)
                hsh = utils_misc.generate_random_string(4)
                dst_bad = (os.path.join(backup_dir,
                                        "%s.bad.%s" % (basename, hsh)))
                dst_good = (os.path.join(backup_dir,
                                         "%s.good.%s" % (basename, hsh)))
                if action == 'backup':
                    bkp_set = [[src_bad, dst_bad], [src_good, dst_good]]
                elif action == 'restore':
                    bkp_set = [[src_good, src_bad]]

            if not bkp_set:
                logging.error("No backup sets for action: %s, state: %s",
                              action, good)

            return bkp_set

        image_filename = self.image_filename
        backup_dir = params.get("backup_dir", "")
        if not os.path.isabs(backup_dir):
            backup_dir = os.path.join(root_dir, backup_dir)
        if params.get('image_raw_device') == 'yes':
            iname = "raw_device"
            iformat = params.get("image_format", "qcow2")
            ifilename = "%s.%s" % (iname, iformat)
            ifilename = utils_misc.get_path(root_dir, ifilename)
            backup_set = get_backup_set(ifilename, backup_dir, action, good)
            backup_func = backup_raw_device
        else:
            backup_set = get_backup_set(image_filename, backup_dir, action,
                                        good)
            backup_func = backup_image_file

        if action == 'backup':
            image_dir = os.path.dirname(image_filename)
            image_dir_disk_free = utils.freespace(image_dir)

            backup_size = 0
            for src, dst in backup_set:
                if os.path.isfile(src):
                    backup_size += os.path.getsize(src)

            minimum_disk_free = 1.2 * backup_size
            if image_dir_disk_free < minimum_disk_free:
                image_dir_disk_free_gb = float(image_dir_disk_free) / 10**9
                backup_size_gb = float(backup_size) / 10**9
                minimum_disk_free_gb = float(minimum_disk_free) / 10**9
                logging.error("Free space on %s: %.1f GB", image_dir,
                              image_dir_disk_free_gb)
                logging.error("Backup size: %.1f GB", backup_size_gb)
                logging.error("Minimum free space acceptable: %.1f GB",
                              minimum_disk_free_gb)
                logging.error("Available disk space is not sufficient for a"
                              "full backup. Skipping backup...")
                return

        for src, dst in backup_set:
            if action == 'backup' and skip_existing and os.path.exists(dst):
                continue
            backup_func(src, dst)
Beispiel #10
0
    def backup_image(self, 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 = self.image_filename
        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)
Beispiel #11
0
 def start(self):
     self.initial_space = utils.freespace(self.device)
     self.start_time = time.time()
Beispiel #12
0
    def backup_image(self, 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 = self.image_filename
        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)