def test_records_readahead(nydus_anchor, nydus_image): nydus_image.set_backend(Backend.BACKEND_PROXY).create_image() rafs_conf = RafsConf(nydus_anchor, nydus_image) rafs_conf.enable_records_readahead(interval=1).set_rafs_backend( Backend.LOCALFS, image=nydus_image) rafs = RafsMount(nydus_anchor, nydus_image, rafs_conf) rafs.mount() wg = WorkloadGen(nydus_anchor.mount_point, nydus_image.rootfs()) # TODO: Run several parallel read workers against the mount_point wg.setup_workload_generator() wg.torture_read(8, 5) wg.finish_torture_read() rafs.umount() utils.clean_pagecache() rafs.mount() wg.torture_read(8, 5) wg.finish_torture_read()
def test_basic( nydus_anchor, nydus_image: RafsImage, io_duration, backend, rafs_conf: RafsConf, fs_version, ): """ title: Basic functionality test description: Mount rafs with different mount options pass_criteria: - Rafs can be mounted. - Rafs can be unmounted. """ nydus_image.set_backend(backend, blob_dir=()).create_image(fs_version=fs_version) rafs_conf.set_rafs_backend(backend) rafs = RafsMount(nydus_anchor, nydus_image, rafs_conf) rafs.mount() assert rafs.is_mounted() workload_gen = WorkloadGen(nydus_anchor.mount_point, nydus_image.rootfs()) workload_gen.setup_workload_generator() workload_gen.io_read(io_duration) nydus_anchor.check_nydusd_health() assert workload_gen.io_error == False assert workload_gen.verify_entire_fs() assert rafs.is_mounted() rafs.umount()
def test_build_image(nydus_anchor, nydus_scratch_image: RafsImage, rafs_conf: RafsConf): """ title: Build nydus image description: Build nydus image from rootfs generating proper bootstrap and blob pass_criteria: - Image can successfully builded and mounted - Rafs can be unmounted and do a small account of read io and attr operation - Try let image builder upload blob itself. """ dist = Distributor(nydus_scratch_image.rootfs(), 80, 1) dist.generate_tree() dist.put_directories(100) dist.put_hardlinks(90) dist.put_symlinks(200) dist.put_multiple_files(random.randint(20, 28), Size(10, Unit.MB)) dist.put_multiple_chinese_files(random.randint(20, 28), Size(20, Unit.KB)) Whiteout().whiteout_one_file(nydus_scratch_image.rootfs(), "i/am/troublemaker/foo") nydus_scratch_image.set_backend(Backend.BACKEND_PROXY).create_image() rafs_conf.set_rafs_backend(backend_type=Backend.BACKEND_PROXY) rafs_conf.dump_rafs_conf() rafs = RafsMount(nydus_anchor, nydus_scratch_image, rafs_conf) wg = WorkloadGen(nydus_anchor.mount_point, nydus_scratch_image.rootfs()) rafs.mount() assert wg.verify_entire_fs() rafs.umount()
def test_large_file(nydus_anchor, compressor, backend, amplified_size): _tmp_dir = tempfile.TemporaryDirectory(dir=nydus_anchor.workspace) large_file_dir = _tmp_dir.name dist = Distributor(large_file_dir, 3, 3) dist.generate_tree() dist.put_single_file(Size(20, Unit.MB)) dist.put_single_file(Size(10891, Unit.KB)) dist.put_multiple_files(10, Size(2, Unit.MB)) dist.put_multiple_files(10, Size(4, Unit.MB)) image = RafsImage(nydus_anchor, large_file_dir, "bs_large", "blob_large") image.set_backend(backend).create_image(compressor=compressor) rafs_conf = (RafsConf(nydus_anchor, image).enable_rafs_blobcache().amplify_io( amplified_size).set_rafs_backend(backend, image=image)) rafs = RafsMount(nydus_anchor, image, rafs_conf) rafs.thread_num(4).mount() workload_gen = WorkloadGen(nydus_anchor.mount_point, large_file_dir) workload_gen.setup_workload_generator() workload_gen.torture_read(8, 5) workload_gen.finish_torture_read() assert not workload_gen.io_error rafs.umount() image.clean_up()
def test_prefetch_with_cache( nydus_anchor, nydus_scratch_image: RafsImage, rafs_conf: RafsConf, thread_cnt, compressor, is_cache_compressed, ): """ title: Prefetch from various backend description: - Enable rafs backend blob cache, as it is disabled by default pass_criteria: - Rafs can be mounted. - Rafs can be unmounted. """ rafs_conf.enable_rafs_blobcache(is_compressed=is_cache_compressed) rafs_conf.set_rafs_backend(Backend.BACKEND_PROXY, prefix="object_prefix/") rafs_conf.enable_fs_prefetch(threads_count=4, bandwidth_rate=Size(40, Unit.MB).B) rafs_conf.dump_rafs_conf() dist = Distributor(nydus_scratch_image.rootfs(), 4, 4) dist.generate_tree() dist.put_directories(20) dist.put_multiple_files(40, Size(3, Unit.MB)) dist.put_hardlinks(6) dist.put_multiple_chinese_files(random.randint(20, 28), Size(20, Unit.KB)) nydus_scratch_image.set_backend(Backend.BACKEND_PROXY, prefix="object_prefix/").create_image( compressor=compressor, readahead_policy="fs", readahead_files="/".encode(), ) rafs = RafsMount(nydus_anchor, nydus_scratch_image, rafs_conf) rafs.thread_num(4).mount() nc = NydusAPIClient(rafs.get_apisock()) workload_gen = WorkloadGen(nydus_anchor.mount_point, nydus_scratch_image.rootfs()) m = nc.get_blobcache_metrics() time.sleep(0.3) assert m["prefetch_data_amount"] != 0 workload_gen.setup_workload_generator() workload_gen.torture_read(thread_cnt, 10) assert NydusAnchor.check_nydusd_health() workload_gen.finish_torture_read() assert not workload_gen.io_error # In this way, we can check if nydusd is crashed. assert rafs.is_mounted() rafs.umount()
def test_blobcache( nydus_anchor: NydusAnchor, nydus_image: RafsImage, rafs_conf: RafsConf, compressor, backend, ): """ Allocate a file with local test working directory. Loop the file so to get a small file system which is easy to get full. Change blob cache location the above test blobdir """ blobdir = "/blobdir" blob_backend = "blob_backend" fd = os.open(blob_backend, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) os.posix_fallocate(fd, 0, 1024 * 1024 * 4) os.close(fd) utils.execute(["mkfs.ext4", "-F", blob_backend]) utils.execute(["mount", blob_backend, blobdir]) rafs_conf.enable_rafs_blobcache() rafs_conf.set_rafs_backend(backend) rafs_conf.dump_rafs_conf() cache_file = os.listdir(blobdir) assert len(cache_file) == 1 rafs = RafsMount(nydus_anchor, nydus_image, rafs_conf) rafs.mount() assert rafs.is_mounted() workload_gen = WorkloadGen(nydus_anchor.mount_point, nydus_anchor.source_dir) workload_gen.setup_workload_generator() workload_gen.torture_read(4, 15) nydus_anchor.start_stats_checker() workload_gen.finish_torture_read() nydus_anchor.stop_stats_checker() cache_file = os.listdir(blobdir) assert len(cache_file) >= 2 if workload_gen.io_error: warnings.warn( UserWarning("Rafs will return EIO if blobcache file is full")) rafs.umount() ret, _ = utils.execute(["umount", blobdir]) assert ret os.unlink(blob_backend)
def test_blobcache_recovery( nydus_anchor: NydusAnchor, rafs_conf: RafsConf, nydus_scratch_image: RafsImage, ): rafs_conf.set_rafs_backend(Backend.BACKEND_PROXY) rafs_conf.enable_fs_prefetch() rafs_conf.enable_rafs_blobcache() rafs_conf.dump_rafs_conf() dist = Distributor(nydus_scratch_image.rootfs(), 8, 2) dist.generate_tree() dirs = dist.put_directories(20) dist.put_multiple_files(100, Size(64, Unit.KB)) dist.put_symlinks(30) dist.put_hardlinks(20) dist.put_multiple_files(40, Size(64, Unit.KB)) dist.put_single_file(Size(3, Unit.MB), name="test") nydus_scratch_image.set_backend(Backend.BACKEND_PROXY).create_image() rafs = RafsMount(nydus_anchor, nydus_scratch_image, rafs_conf) rafs.prefetch_files("/").mount() wg = WorkloadGen(nydus_anchor.mount_point, nydus_scratch_image.rootfs()) wg.setup_workload_generator() wg.torture_read(4, 4) # Hopefully, prefetch can be done in 5 secondes. time.sleep(5) wg.finish_torture_read() rafs.umount() rafs2 = RafsMount(nydus_anchor, nydus_scratch_image, rafs_conf) rafs2.mount() wg.torture_read(4, 4) time.sleep(0.5) nc = NydusAPIClient(rafs2.get_apisock()) begin = nc.get_backend_metrics()["read_amount_total"] time.sleep(1) end = nc.get_backend_metrics()["read_amount_total"] assert end == begin == 0 wg.finish_torture_read()
def test_prefetch_without_cache(nydus_anchor: NydusAnchor, nydus_scratch_image: RafsImage, rafs_conf: RafsConf): """Files prefetch test 1. relative hinted prefetch files 2. absolute hinted prefetch files 3. source rootfs root dir. """ rafs_conf.enable_fs_prefetch().set_rafs_backend(Backend.BACKEND_PROXY) rafs_conf.dump_rafs_conf() dist = Distributor(nydus_scratch_image.rootfs(), 4, 4) dist.generate_tree() dist.put_directories(20) dist.put_multiple_files(40, Size(8, Unit.KB)) dist.put_hardlinks(6) dist.put_multiple_chinese_files(random.randint(20, 28), Size(20, Unit.KB)) hint_files = ["/"] hint_files.extend(dist.files) hint_files.extend(dist.dirs) hint_files.extend(dist.symlinks) hint_files.extend(dist.hardlinks) hint_files = [os.path.join("/", p) for p in hint_files] hint_files = "\n".join(hint_files) nydus_scratch_image.set_backend(Backend.BACKEND_PROXY).create_image( readahead_policy="fs", readahead_files=hint_files.encode()) rafs = RafsMount(nydus_anchor, nydus_scratch_image, rafs_conf) rafs.mount() assert rafs.is_mounted() workload_gen = WorkloadGen(nydus_anchor.mount_point, nydus_scratch_image.rootfs()) # TODO: Run several parallel read workers against the mount_point workload_gen.setup_workload_generator() workload_gen.torture_read(8, 5) workload_gen.finish_torture_read() assert NydusAnchor.check_nydusd_health() assert not workload_gen.io_error assert rafs.is_mounted() rafs.umount()
def test_global_metrics(nydus_anchor, nydus_image: RafsImage, rafs_conf: RafsConf): rafs_id = "/" rafs_conf.enable_files_iostats().set_rafs_backend(Backend.OSS) nydus_image.set_backend(Backend.OSS).create_image() rafs = RafsMount(nydus_anchor, nydus_image, rafs_conf) rafs.mount() nc = NydusAPIClient(rafs.get_apisock()) gm = nc.get_global_metrics() assert gm["files_account_enabled"] == True assert gm["measure_latency"] == True file_counters = nc.get_files_metrics(rafs_id) assert len(file_counters) logging.info("There are %d file counters created.", len(file_counters)) wg = WorkloadGen(nydus_anchor.mount_point, nydus_image.rootfs()) wg.setup_workload_generator() wg.io_read(4) file_counters = nc.get_files_metrics(rafs_id) assert file_counters is not None and len(file_counters) logging.info("There are %d file counters created after some read.", len(file_counters)) if len(file_counters): k = random.choice(list(file_counters)) logging.info("ino: %s, stats: %s", k, file_counters[k]) gm_old = nc.get_global_metrics() wg.io_read(4) gm_new = nc.get_global_metrics() assert gm_new["data_read"] > gm_old["data_read"] assert (gm_new["fop_hits"][nydusd_client.Fop.Read.get_value()] > gm_old["fop_hits"][nydusd_client.Fop.Read.get_value()]) rafs.umount()
def test_iostats(nydus_anchor: NydusAnchor, nydus_image: RafsImage, rafs_conf: RafsConf): rafs_id = "/" rafs_conf.enable_files_iostats().enable_latest_read_files( ).set_rafs_backend(Backend.OSS) nydus_image.set_backend(Backend.OSS).create_image() rafs = RafsMount(nydus_anchor, nydus_image, rafs_conf) rafs.mount() assert rafs.is_mounted() nc = NydusAPIClient(rafs.get_apisock()) duration = 5 wg = WorkloadGen(nydus_anchor.mount_point, nydus_image.rootfs()) wg.setup_workload_generator() wg.torture_read(4, duration) while duration: time.sleep(1) duration -= 1 nc.get_global_metrics() nc.get_files_metrics(rafs_id) nc.get_backend_metrics(rafs_id) wg.finish_torture_read() duration = 7 wg.torture_read(4, duration) # Disable it firstly and then enable it. # TODO: files metrics can't be toggled dynamically now. Try to implement it. # nc.disable_files_metrics(rafs_id) # nc.enable_files_metrics(rafs_id) r = nc.get_latest_files_metrics(rafs_id) print(r) while duration: time.sleep(1) duration -= 1 nc.get_files_metrics(rafs_id) wg.finish_torture_read() rafs.umount()