def setup_blkio_cgroup(srcpath, dstpath, bps_limit, execute=utils.execute): if not bps_limit: return None try: srcdev = utils.get_blkdev_major_minor(srcpath) except exception.Error as e: msg = ( _('Failed to get device number for read throttling: %(error)s') % { 'error': e }) LOG.error(msg) srcdev = None try: dstdev = utils.get_blkdev_major_minor(dstpath) except exception.Error as e: msg = ( _('Failed to get device number for write throttling: %(error)s') % { 'error': e }) LOG.error(msg) dstdev = None if not srcdev and not dstdev: return None group_name = CONF.volume_copy_blkio_cgroup_name try: execute('cgcreate', '-g', 'blkio:%s' % group_name, run_as_root=True) except processutils.ProcessExecutionError: LOG.warn(_('Failed to create blkio cgroup')) return None try: if srcdev: execute('cgset', '-r', 'blkio.throttle.read_bps_device=%s %d' % (srcdev, bps_limit), group_name, run_as_root=True) if dstdev: execute('cgset', '-r', 'blkio.throttle.write_bps_device=%s %d' % (dstdev, bps_limit), group_name, run_as_root=True) except processutils.ProcessExecutionError: msg = (_('Failed to setup blkio cgroup to throttle the devices: ' '\'%(src)s\',\'%(dst)s\'') % { 'src': srcdev, 'dst': dstdev }) LOG.warn(msg) return None return ['cgexec', '-g', 'blkio:%s' % group_name]
def setup_blkio_cgroup(srcpath, dstpath, bps_limit, execute=utils.execute): if not bps_limit: LOG.debug('Not using bps rate limiting on volume copy') return None try: srcdev = utils.get_blkdev_major_minor(srcpath) except exception.Error as e: msg = (_('Failed to get device number for read throttling: %(error)s') % {'error': e}) LOG.error(msg) srcdev = None try: dstdev = utils.get_blkdev_major_minor(dstpath) except exception.Error as e: msg = (_('Failed to get device number for write throttling: %(error)s') % {'error': e}) LOG.error(msg) dstdev = None if not srcdev and not dstdev: return None group_name = CONF.volume_copy_blkio_cgroup_name LOG.debug('Setting rate limit to %s bps for blkio ' 'group: %s' % (bps_limit, group_name)) try: execute('cgcreate', '-g', 'blkio:%s' % group_name, run_as_root=True) except processutils.ProcessExecutionError: LOG.warn(_('Failed to create blkio cgroup')) return None try: if srcdev: execute('cgset', '-r', 'blkio.throttle.read_bps_device=%s %d' % (srcdev, bps_limit), group_name, run_as_root=True) if dstdev: execute('cgset', '-r', 'blkio.throttle.write_bps_device=%s %d' % (dstdev, bps_limit), group_name, run_as_root=True) except processutils.ProcessExecutionError: msg = (_('Failed to setup blkio cgroup to throttle the devices: ' '\'%(src)s\',\'%(dst)s\'') % {'src': srcdev, 'dst': dstdev}) LOG.warn(msg) return None return ['cgexec', '-g', 'blkio:%s' % group_name]
def _get_device_number(self, path): try: return utils.get_blkdev_major_minor(path) except exception.Error as e: LOG.error( _LE('Failed to get device number for throttling: ' '%(error)s'), {'error': e})
def test_get_blkdev_is_chr(self, mock_isblk, mock_ischr, mock_stat): path = '/some/path' output = utils.get_blkdev_major_minor(path, lookup_for_file=False) mock_stat.assert_called_once_with(path) mock_isblk.assert_called_once_with(mock_stat.return_value.st_mode) mock_ischr.assert_called_once_with(mock_stat.return_value.st_mode) self.assertIs(None, output)
def test_get_blkdev_major_minor(self, mock_stat): class stat_result: st_mode = 0o60660 st_rdev = os.makedev(253, 7) test_device = '/dev/made_up_blkdev' mock_stat.return_value = stat_result dev = utils.get_blkdev_major_minor(test_device) self.assertEqual('253:7', dev) mock_stat.assert_called_once_with(test_device)
def test_get_blkdev_major_minor(self, mock_stat): class stat_result: st_mode = 0o60660 st_rdev = os.makedev(253, 7) test_device = '/dev/made_up_blkdev' mock_stat.return_value = stat_result dev = utils.get_blkdev_major_minor(test_device) self.assertEqual('253:7', dev) mock_stat.aseert_called_once_with(test_device)
def _test_get_blkdev_major_minor_file(self, test_partition, mock_exec, mock_stat): mock_exec.return_value = ( 'Filesystem Size Used Avail Use%% Mounted on\n' '%s 4096 2048 2048 50%% /tmp\n' % test_partition, None) test_file = '/tmp/file' test_disk = '/dev/made_up_disk' class stat_result_file: st_mode = 0o660 class stat_result_partition: st_mode = 0o60660 st_rdev = os.makedev(8, 65) class stat_result_disk: st_mode = 0o60660 st_rdev = os.makedev(8, 64) def fake_stat(path): try: return { test_file: stat_result_file, test_partition: stat_result_partition, test_disk: stat_result_disk }[path] except KeyError: raise OSError mock_stat.side_effect = fake_stat dev = utils.get_blkdev_major_minor(test_file) mock_stat.assert_any_call(test_file) mock_exec.assert_called_once_with('df', test_file) if test_partition.startswith('/'): mock_stat.assert_any_call(test_partition) mock_stat.assert_any_call(test_disk) return dev
def test_get_blkdev_major_minor_file(self, mock_exec, mock_stat): mock_exec.return_value = ( 'Filesystem Size Used Avail Use% Mounted on\n' '/dev/made_up_disk1 4096 2048 2048 50% /tmp\n', None) test_file = '/tmp/file' test_partition = '/dev/made_up_disk1' test_disk = '/dev/made_up_disk' class stat_result_file: st_mode = 0o660 class stat_result_partition: st_mode = 0o60660 st_rdev = os.makedev(8, 65) class stat_result_disk: st_mode = 0o60660 st_rdev = os.makedev(8, 64) def fake_stat(path): try: return { test_file: stat_result_file, test_partition: stat_result_partition, test_disk: stat_result_disk }[path] except KeyError: raise OSError mock_stat.side_effect = fake_stat dev = utils.get_blkdev_major_minor(test_file) self.assertEqual('8:64', dev) mock_exec.aseert_called_once_with(test_file) mock_stat.aseert_called_once_with(test_file) mock_stat.aseert_called_once_with(test_partition) mock_stat.aseert_called_once_with(test_disk)
def test_get_blkdev_major_minor_file(self, mock_exec, mock_stat): mock_exec.return_value = ( 'Filesystem Size Used Avail Use% Mounted on\n' '/dev/made_up_disk1 4096 2048 2048 50% /tmp\n', None) test_file = '/tmp/file' test_partition = '/dev/made_up_disk1' test_disk = '/dev/made_up_disk' class stat_result_file: st_mode = 0o660 class stat_result_partition: st_mode = 0o60660 st_rdev = os.makedev(8, 65) class stat_result_disk: st_mode = 0o60660 st_rdev = os.makedev(8, 64) def fake_stat(path): try: return {test_file: stat_result_file, test_partition: stat_result_partition, test_disk: stat_result_disk}[path] except KeyError: raise OSError mock_stat.side_effect = fake_stat dev = utils.get_blkdev_major_minor(test_file) self.assertEqual('8:64', dev) mock_exec.aseert_called_once_with(test_file) mock_stat.aseert_called_once_with(test_file) mock_stat.aseert_called_once_with(test_partition) mock_stat.aseert_called_once_with(test_disk)
def _test_get_blkdev_major_minor_file(self, test_partition, mock_exec, mock_stat): mock_exec.return_value = ( 'Filesystem Size Used Avail Use%% Mounted on\n' '%s 4096 2048 2048 50%% /tmp\n' % test_partition, None) test_file = '/tmp/file' test_disk = '/dev/made_up_disk' class stat_result_file(object): st_mode = 0o660 class stat_result_partition(object): st_mode = 0o60660 st_rdev = os.makedev(8, 65) class stat_result_disk(object): st_mode = 0o60660 st_rdev = os.makedev(8, 64) def fake_stat(path): try: return {test_file: stat_result_file, test_partition: stat_result_partition, test_disk: stat_result_disk}[path] except KeyError: raise OSError mock_stat.side_effect = fake_stat dev = utils.get_blkdev_major_minor(test_file) mock_stat.assert_any_call(test_file) mock_exec.assert_called_once_with('df', test_file) if test_partition.startswith('/'): mock_stat.assert_any_call(test_partition) mock_stat.assert_any_call(test_disk) return dev
def _get_device_number(self, path): try: return utils.get_blkdev_major_minor(path) except exception.Error as e: LOG.error(_LE('Failed to get device number for throttling: ' '%(error)s'), {'error': e})