def test_read_only(self): for arg in self.path_or_fd(self.mountpoint): with self.subTest(type=type(arg)): btrfsutil.set_subvolume_read_only(arg) self.assertTrue(btrfsutil.get_subvolume_read_only(arg)) self.assertTrue(btrfsutil.subvolume_info(arg).flags & 1) btrfsutil.set_subvolume_read_only(arg, False) self.assertFalse(btrfsutil.get_subvolume_read_only(arg)) self.assertFalse(btrfsutil.subvolume_info(arg).flags & 1) btrfsutil.set_subvolume_read_only(arg, True) self.assertTrue(btrfsutil.get_subvolume_read_only(arg)) self.assertTrue(btrfsutil.subvolume_info(arg).flags & 1) btrfsutil.set_subvolume_read_only(arg, False)
def test_read_only(self): for arg in self.path_or_fd(self.mountpoint): with self.subTest(type=type(arg)): btrfsutil.set_subvolume_read_only(arg) self.assertTrue(btrfsutil.get_subvolume_read_only(arg)) self.assertTrue(btrfsutil.subvolume_info(arg).flags & 1) btrfsutil.set_subvolume_read_only(arg, False) self.assertFalse(btrfsutil.get_subvolume_read_only(arg)) self.assertFalse(btrfsutil.subvolume_info(arg).flags & 1) btrfsutil.set_subvolume_read_only(arg, True) self.assertTrue(btrfsutil.get_subvolume_read_only(arg)) self.assertTrue(btrfsutil.subvolume_info(arg).flags & 1) btrfsutil.set_subvolume_read_only(arg, False)
def test_create_snapshot(self): subvol = os.path.join(self.mountpoint, 'subvol') btrfsutil.create_subvolume(subvol) os.mkdir(os.path.join(subvol, 'dir')) for i, arg in enumerate(self.path_or_fd(subvol)): with self.subTest(type=type(arg)): snapshots_dir = os.path.join(self.mountpoint, 'snapshots{}'.format(i)) os.mkdir(snapshots_dir) snapshot = os.path.join(snapshots_dir, 'snapshot') btrfsutil.create_snapshot(subvol, snapshot + '1') self.assertTrue(btrfsutil.is_subvolume(snapshot + '1')) self.assertTrue(os.path.exists(os.path.join(snapshot + '1', 'dir'))) btrfsutil.create_snapshot(subvol, (snapshot + '2').encode()) self.assertTrue(btrfsutil.is_subvolume(snapshot + '2')) self.assertTrue(os.path.exists(os.path.join(snapshot + '2', 'dir'))) if HAVE_PATH_LIKE: btrfsutil.create_snapshot(subvol, PurePath(snapshot + '3')) self.assertTrue(btrfsutil.is_subvolume(snapshot + '3')) self.assertTrue(os.path.exists(os.path.join(snapshot + '3', 'dir'))) nested_subvol = os.path.join(subvol, 'nested') more_nested_subvol = os.path.join(nested_subvol, 'more_nested') btrfsutil.create_subvolume(nested_subvol) btrfsutil.create_subvolume(more_nested_subvol) os.mkdir(os.path.join(more_nested_subvol, 'nested_dir')) snapshot = os.path.join(self.mountpoint, 'snapshot') btrfsutil.create_snapshot(subvol, snapshot + '1') # Dummy subvolume. self.assertEqual(os.stat(os.path.join(snapshot + '1', 'nested')).st_ino, 2) self.assertFalse(os.path.exists(os.path.join(snapshot + '1', 'nested', 'more_nested'))) btrfsutil.create_snapshot(subvol, snapshot + '2', recursive=True) self.assertTrue(os.path.exists(os.path.join(snapshot + '2', 'nested/more_nested/nested_dir'))) transid = btrfsutil.create_snapshot(subvol, snapshot + '3', recursive=True, no_wait=True) self.assertTrue(os.path.exists(os.path.join(snapshot + '3', 'nested/more_nested/nested_dir'))) self.assertGreater(transid, 0) btrfsutil.create_snapshot(subvol, snapshot + '4', read_only=True) self.assertTrue(btrfsutil.get_subvolume_read_only(snapshot + '4'))
def get_subvolume_from(self, filesystem_path: Path) -> Optional[Subvolume]: logger = self._logger if not filesystem_path.exists(): raise SubvolumeError( f"The '{filesystem_path}' path does not exist!") if not filesystem_path.is_dir(): raise SubvolumeError( f"The '{filesystem_path}' path does not represent a directory!" ) try: filesystem_path_str = str(filesystem_path) if btrfsutil.is_subvolume(filesystem_path_str): subvolume_id = btrfsutil.subvolume_id(filesystem_path_str) subvolume_path = btrfsutil.subvolume_path( filesystem_path_str, subvolume_id) subvolume_read_only = btrfsutil.get_subvolume_read_only( filesystem_path_str) subvolume_info = btrfsutil.subvolume_info( filesystem_path_str, subvolume_id) self_uuid = default_if_none( try_convert_bytes_to_uuid(subvolume_info.uuid), constants.EMPTY_UUID, ) parent_uuid = default_if_none( try_convert_bytes_to_uuid(subvolume_info.parent_uuid), constants.EMPTY_UUID, ) return Subvolume( filesystem_path, subvolume_path, datetime.fromtimestamp(subvolume_info.otime), UuidRelation(self_uuid, parent_uuid), NumIdRelation(subvolume_info.id, subvolume_info.parent_id), subvolume_read_only, ) except btrfsutil.BtrfsUtilError as e: logger.exception("btrfsutil call failed!") raise SubvolumeError( f"Could not initialize the subvolume for '{filesystem_path}'!" ) from e return None
def test_create_snapshot(self): subvol = os.path.join(self.mountpoint, 'subvol') btrfsutil.create_subvolume(subvol) os.mkdir(os.path.join(subvol, 'dir')) for i, arg in enumerate(self.path_or_fd(subvol)): with self.subTest(type=type(arg)): snapshots_dir = os.path.join(self.mountpoint, 'snapshots{}'.format(i)) os.mkdir(snapshots_dir) snapshot = os.path.join(snapshots_dir, 'snapshot') btrfsutil.create_snapshot(subvol, snapshot + '1') self.assertTrue(btrfsutil.is_subvolume(snapshot + '1')) self.assertTrue(os.path.exists(os.path.join(snapshot + '1', 'dir'))) btrfsutil.create_snapshot(subvol, (snapshot + '2').encode()) self.assertTrue(btrfsutil.is_subvolume(snapshot + '2')) self.assertTrue(os.path.exists(os.path.join(snapshot + '2', 'dir'))) if HAVE_PATH_LIKE: btrfsutil.create_snapshot(subvol, PurePath(snapshot + '3')) self.assertTrue(btrfsutil.is_subvolume(snapshot + '3')) self.assertTrue(os.path.exists(os.path.join(snapshot + '3', 'dir'))) nested_subvol = os.path.join(subvol, 'nested') more_nested_subvol = os.path.join(nested_subvol, 'more_nested') btrfsutil.create_subvolume(nested_subvol) btrfsutil.create_subvolume(more_nested_subvol) os.mkdir(os.path.join(more_nested_subvol, 'nested_dir')) snapshot = os.path.join(self.mountpoint, 'snapshot') btrfsutil.create_snapshot(subvol, snapshot + '1') # Dummy subvolume. self.assertEqual(os.stat(os.path.join(snapshot + '1', 'nested')).st_ino, 2) self.assertFalse(os.path.exists(os.path.join(snapshot + '1', 'nested', 'more_nested'))) btrfsutil.create_snapshot(subvol, snapshot + '2', recursive=True) self.assertTrue(os.path.exists(os.path.join(snapshot + '2', 'nested/more_nested/nested_dir'))) transid = btrfsutil.create_snapshot(subvol, snapshot + '3', recursive=True, async_=True) self.assertTrue(os.path.exists(os.path.join(snapshot + '3', 'nested/more_nested/nested_dir'))) self.assertGreater(transid, 0) btrfsutil.create_snapshot(subvol, snapshot + '4', read_only=True) self.assertTrue(btrfsutil.get_subvolume_read_only(snapshot + '4'))