Example #1
0
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()
Example #2
0
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()
Example #3
0
def test_prefetch_with_cache(
    nydus_anchor: NydusAnchor,
    nydus_scratch_image: RafsImage,
    nydus_scratch_parent_image: RafsImage,
    rafs_conf: RafsConf,
):
    parent_rootfs = nydus_scratch_parent_image.rootfs()
    upper_rootfs = nydus_scratch_image.rootfs()

    rafs_conf.enable_validation()
    rafs_conf.set_rafs_backend(Backend.OSS)
    rafs_conf.enable_rafs_blobcache()
    rafs_conf.enable_fs_prefetch(threads_count=4, merging_size=512 * 1024)
    rafs_conf.dump_rafs_conf()

    dist_parent = Distributor(parent_rootfs, 6, 4)
    dist_parent.generate_tree()
    dist_parent.put_directories(20)
    dist_parent.put_multiple_files(100, Size(64, Unit.KB))
    dist_parent.put_symlinks(30)
    dist_parent.put_hardlinks(20)

    dist_upper = Distributor(upper_rootfs, 3, 8)
    dist_upper.generate_tree()
    dist_upper.put_multiple_files(27, Size(3, Unit.MB))
    dist_upper.put_symlinks(5)

    # hint_files_parent = dist_parent.put_multiple_files(1000, Size(8, Unit.KB))
    # hint_files_parent = [os.path.join(parent_rootfs, p) for p in hint_files_parent]
    # hint_files_parent = "\n".join(hint_files_parent)

    nydus_scratch_parent_image.set_backend(Backend.OSS).create_image(
        readahead_policy="fs", readahead_files="/".encode())

    hint_files = dist_upper.put_multiple_files(1000, Size(8, Unit.KB))
    hint_files.extend(dist_upper.put_multiple_empty_files(200))

    hint_files = [os.path.join("/", p) for p in hint_files]
    hint_files = "\n".join(hint_files)

    nydus_scratch_image.set_backend(Backend.OSS).create_image(
        parent_image=nydus_scratch_parent_image,
        readahead_policy="fs",
        readahead_files=hint_files.encode(),
    )

    nydus_anchor.mount_overlayfs(
        [nydus_scratch_image.rootfs(),
         nydus_scratch_parent_image.rootfs()])

    rafs = RafsMount(nydus_anchor, nydus_scratch_image, rafs_conf)
    rafs.thread_num(5).mount()

    workload_gen = WorkloadGen(nydus_anchor.mount_point,
                               nydus_anchor.overlayfs)
    workload_gen.setup_workload_generator()

    assert workload_gen.verify_entire_fs()
    workload_gen.torture_read(5, 20)
    workload_gen.finish_torture_read()
Example #4
0
def test_meta(nydus_anchor: NydusAnchor, rafs_conf: RafsConf,
              nydus_scratch_image: RafsImage):
    anchor = nydus_anchor
    rafs_conf.set_rafs_backend(Backend.BACKEND_PROXY).enable_rafs_blobcache()
    rafs_conf.dump_rafs_conf()

    dist = Distributor(nydus_scratch_image.rootfs(), 8, 5)
    dist.generate_tree()

    xattr_verifier = verifier.XattrVerifier(anchor.mount_point, dist)
    xattr_verifier.scratch(nydus_scratch_image.rootfs())

    symlink_verifier = verifier.SymlinkVerifier(anchor.mount_point, dist)
    symlink_verifier.scratch()

    # Do some meta operations on scratch dir before creating rafs image file.
    # Use scratch dir as image source dir as we just prepared test meta into it.
    nydus_scratch_image.set_backend(Backend.BACKEND_PROXY).create_image()
    rafs = RafsMount(anchor, nydus_scratch_image, rafs_conf)
    rafs.thread_num(4).mount()
    assert rafs.is_mounted()

    xattr_verifier.verify(anchor.mount_point)
    symlink_verifier.verify(anchor.mount_point, nydus_scratch_image.rootfs())

    workload_gen = WorkloadGen(anchor.mount_point,
                               nydus_scratch_image.rootfs())
    workload_gen.setup_workload_generator()

    workload_gen.torture_read(10, 3)
    workload_gen.finish_torture_read()

    assert workload_gen.io_error == False
    assert anchor.check_nydusd_health()
Example #5
0
def test_layered_rebuild(
    nydus_anchor,
    nydus_scratch_image: RafsImage,
    nydus_scratch_parent_image: RafsImage,
    rafs_conf: RafsConf,
    backend,
):
    """
    title: Layered image rebuild
        description:
            - Parent and upper have files whose contents are exactly the same.
            - Use files stats to check if file is overlayed.
            - Files with the same name but different modes.
            - Files with xattr in parent should be shadowed.
        pass_criteria:
          - Mount successfully.
          - No data corruption.
    """
    rafs_conf.set_rafs_backend(backend)
    rafs_conf.enable_rafs_blobcache()
    rafs_conf.dump_rafs_conf()

    parent_rootfs = nydus_scratch_parent_image.rootfs()
    upper_rootfs = nydus_scratch_image.rootfs()

    nydus_anchor.mount_overlayfs(
        [nydus_scratch_image.rootfs(),
         nydus_scratch_parent_image.rootfs()])

    shared_files = []

    dist_parent = Distributor(parent_rootfs, 6, 4)
    dist_parent.generate_tree()
    shared_files.extend(dist_parent.put_multiple_files(100, Size(64, Unit.KB)))
    shared_files.extend(dist_parent.put_symlinks(30))
    shared_files.extend(dist_parent.put_hardlinks(30))
    xattr_verifier = XattrVerifier(parent_rootfs, dist_parent)
    Whiteout.mirror_files(shared_files, parent_rootfs, upper_rootfs)

    xattr_verifier.scratch(parent_rootfs)

    nydus_scratch_parent_image.set_backend(backend).create_image()
    nydus_scratch_image.set_backend(backend).create_image(
        parent_image=nydus_scratch_parent_image)

    rafs = RafsMount(nydus_anchor, nydus_scratch_image, rafs_conf)
    rafs.mount()

    workload_gen = WorkloadGen(nydus_anchor.mount_point,
                               nydus_anchor.overlayfs)
    workload_gen.setup_workload_generator()

    xattr_verifier.verify(nydus_anchor.mount_point)

    assert workload_gen.verify_entire_fs()
    workload_gen.torture_read(5, 4)

    workload_gen.finish_torture_read()
Example #6
0
def test_specified_prefetch(
    nydus_anchor: NydusAnchor,
    rafs_conf: RafsConf,
    nydus_scratch_image: RafsImage,
    backend,
):
    """
    description:
        Nydusd can have a list including files and directories input when started.
        Then it can prefetch files from backend per as to the list.
    """

    rafs_conf.set_rafs_backend(backend)
    rafs_conf.enable_fs_prefetch(prefetch_all=True)
    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).create_image()

    prefetching_files = dirs
    prefetching_files += dist.files[:-10]
    prefetching_files += dist.dirs[:-5]
    prefetching_files += dist.symlinks[:-10]
    # Fuzz
    prefetching_files.append("/a/b/c/d")
    prefetching_files.append(os.path.join("/", "f/g/h/"))

    specified_dirs = " ".join(
        [os.path.join("/", d) for d in prefetching_files])

    rafs = RafsMount(nydus_anchor, nydus_scratch_image, rafs_conf)
    rafs.prefetch_files(specified_dirs).mount()
    wg = WorkloadGen(nydus_anchor.mount_point, nydus_scratch_image.rootfs())

    nc = NydusAPIClient(rafs.get_apisock())
    wg.setup_workload_generator()
    blobcache_metrics = nc.get_blobcache_metrics()
    wg.torture_read(5, 10)

    while blobcache_metrics["prefetch_workers"] != 0:
        time.sleep(0.5)
        blobcache_metrics = nc.get_blobcache_metrics()

    begin = nc.get_backend_metrics()["read_amount_total"]
    time.sleep(1)
    end = nc.get_backend_metrics()["read_amount_total"]

    assert end == begin
    wg.finish_torture_read()
Example #7
0
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()
Example #8
0
def test_file_tail(nydus_anchor: NydusAnchor, nydus_scratch_image: RafsImage,
                   backend):
    """
    description: Read data from file tail
        - Create several files of different sizes
        - Punch hole to each file of which some should have hole tail
        - Create rafs image from test scratch directory.
        - Mount rafs
        - Do some test.
    """
    file_size_list = [
        Size(1, Unit.KB),
        Size(6, Unit.KB),
        Size(2, Unit.MB),
        Size(10034, Unit.KB),
    ]
    file_list = []

    dist = Distributor(nydus_anchor.scratch_dir, 2, 2)
    dist.generate_tree()

    for f_s in file_size_list:
        f_name = dist.put_single_file(f_s)
        file_list.append(f_name)
        # Punch hole
        with utils.pushd(nydus_anchor.scratch_dir):
            with open(f_name, "a+b") as f:
                fallocate(
                    f,
                    f_s.B - 500,
                    1000,
                    mode=FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
                )

    nydus_scratch_image.set_backend(backend).create_image()

    rafs_conf = RafsConf(nydus_anchor, nydus_scratch_image)
    rafs_conf.set_rafs_backend(backend, image=nydus_scratch_image)

    rafs = RafsMount(nydus_anchor, nydus_scratch_image, rafs_conf)
    rafs.mount()

    with utils.pushd(nydus_anchor.mount_point):
        for name in file_list:
            with open(name, "rb") as f:
                size = os.stat(name).st_size
                f.seek(size - 300)
                buf = f.read(1000)
                assert len(buf) == 300

    wg = WorkloadGen(nydus_anchor.mount_point, nydus_scratch_image.rootfs())
    for f in file_list:
        wg.verify_single_file(os.path.join(nydus_anchor.mount_point, f))

    assert wg.io_error == False
Example #9
0
def test_blob_prefetch(nydus_anchor: NydusAnchor,
                       nydus_scratch_image: RafsImage, readahead_policy):
    """
    description:
        For rafs, there are two types of prefetching.
        1. Prefetch files from fs-layer, which means each file is prefetched one by one.
        2. Prefetch directly from backend/blob layer, which means a range will be fetched from blob
    """
    # Try to delete any access log since if it present, bootstrap blob prefetch won't work.
    utils.execute("rm -rf *.access", shell=True)

    dist = Distributor(nydus_scratch_image.rootfs(), 8, 2)
    dist.generate_tree()
    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))

    utils.clean_pagecache()

    hint_files = dist.files[-40:]
    hint_files.extend(dist.symlinks[-20:])

    hint_files = [os.path.join("/", p) for p in hint_files]
    hint_files = "\n".join(hint_files)

    nydus_scratch_image.set_backend(Backend.LOCALFS).create_image(
        readahead_policy=readahead_policy,
        readahead_files=hint_files.encode(),
    )

    rafs_conf = RafsConf(nydus_anchor, nydus_scratch_image)
    rafs_conf.set_rafs_backend(Backend.LOCALFS, image=nydus_scratch_image)
    rafs_conf.enable_records_readahead(interval=1)
    rafs_conf.dump_rafs_conf()

    rafs = RafsMount(nydus_anchor, nydus_scratch_image, rafs_conf)
    with utils.timer("Mount elapse"):
        rafs.thread_num(7).mount()
    assert rafs.is_mounted()

    wg = WorkloadGen(nydus_anchor.mount_point, nydus_scratch_image.rootfs())

    # TODO: Run several parallel read workers against the mount_point
    wg.setup_workload_generator()
    wg.torture_read(5, 5)
    wg.finish_torture_read()

    utils.clean_pagecache()
Example #10
0
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()
Example #11
0
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()
Example #12
0
def test_syscalls(
    nydus_anchor: NydusAnchor,
    nydus_scratch_image: RafsImage,
    rafs_conf: RafsConf,
):

    syscall_helper = "framework/test_syscalls"
    ret, _ = utils.execute(
        ["gcc", "framework/test_syscalls.c", "-o", syscall_helper],
        shell=False,
        print_output=True,
    )
    assert ret

    dist = Distributor(nydus_scratch_image.rootfs(), 2, 2)
    dist.generate_tree()
    dist.put_single_file(Size(8, Unit.KB),
                         pos=nydus_scratch_image.rootfs(),
                         name="xattr_no_kv")
    dist.put_single_file_with_xattr(
        Size(8, Unit.KB),
        ("trusted.nydus.key", ""),
        pos=nydus_scratch_image.rootfs(),
        name="xattr_empty_value",
    )
    dist.put_single_file_with_xattr(
        Size(8, Unit.KB),
        ("trusted.nydus.key", "1234567890"),
        pos=nydus_scratch_image.rootfs(),
        name="xattr_insufficient_buffer",
    )

    nydus_scratch_image.set_backend(Backend.BACKEND_PROXY).create_image()

    rafs_conf.enable_xattr().set_rafs_backend(Backend.BACKEND_PROXY)
    rafs_conf.dump_rafs_conf()

    rafs = RafsMount(nydus_anchor, nydus_scratch_image, rafs_conf)
    rafs.mount()

    for no in [58]:
        ret, _ = utils.execute(
            [syscall_helper, nydus_anchor.mount_point,
             str(no)],
            shell=False,
            print_output=True,
        )
        assert ret
Example #13
0
def test_different_partitions(nydus_anchor: NydusAnchor, rafs_conf):
    loop_file_1 = tempfile.NamedTemporaryFile(suffix="loop")
    loop_file_2 = tempfile.NamedTemporaryFile(suffix="loop")
    loop_mnt_1 = tempfile.TemporaryDirectory(dir=nydus_anchor.workspace)
    loop_mnt_2 = tempfile.TemporaryDirectory(dir=nydus_anchor.workspace)

    os.posix_fallocate(loop_file_1.fileno(), 0, Size(400, Unit.MB).B)
    os.posix_fallocate(loop_file_2.fileno(), 0, Size(400, Unit.MB).B)

    utils.execute(["mkfs.ext4", "-F", loop_file_1.name])
    utils.execute(["mkfs.ext4", "-F", loop_file_2.name])
    utils.execute(["mount", loop_file_1.name, loop_mnt_1.name])
    utils.execute(["mount", loop_file_2.name, loop_mnt_2.name])

    # TODO: Put more special files into
    dist1 = Distributor(loop_mnt_1.name, 5, 7)
    dist1.generate_tree()
    dist1.put_multiple_files(100, Size(12, Unit.KB))

    dist2 = Distributor(loop_mnt_2.name, 5, 7)
    dist2.generate_tree()
    dist2.put_symlinks(20)
    dist2.put_multiple_files(50, Size(12, Unit.KB))

    Whiteout.mirror_files(dist2.files[:20], loop_mnt_2.name, loop_mnt_1.name)

    parent_image = (RafsImage(nydus_anchor, loop_mnt_1.name).set_backend(
        Backend.OSS).create_image())

    image = RafsImage(nydus_anchor, loop_mnt_2.name)
    image.set_backend(Backend.OSS).create_image(parent_image=parent_image)

    rafs_conf.set_rafs_backend(Backend.OSS)
    rafs = RafsMount(nydus_anchor, image, rafs_conf)
    rafs.mount()

    nydus_anchor.mount_overlayfs([image.rootfs(), parent_image.rootfs()])

    wg = WorkloadGen(nydus_anchor.mount_point, nydus_anchor.overlayfs)
    wg.setup_workload_generator()
    wg.torture_read(5, 5)
    wg.finish_torture_read()

    utils.execute(["umount", loop_mnt_1.name])
    utils.execute(["umount", loop_mnt_2.name])

    nydus_anchor.umount_overlayfs()
Example #14
0
def test_blobcache(
    nydus_anchor: NydusAnchor,
    rafs_conf: RafsConf,
    nydus_image: RafsImage,
    nydus_scratch_parent_image: RafsImage,
    thread_cnt,
    io_duration,
):
    dist_parent = Distributor(nydus_scratch_parent_image.rootfs(), 6, 4)
    dist_parent.generate_tree()
    dist_parent.put_multiple_files(20, Size(4, Unit.KB))

    hint_files_parent = [os.path.join("/", p) for p in dist_parent.files[-20:]]
    hint_files_parent = "\n".join(hint_files_parent[-1:])

    nydus_scratch_parent_image.set_backend(Backend.OSS).create_image()
    # shutil.rmtree(nydus_scratch_parent_image.rootfs())
    nydus_image.set_backend(Backend.OSS).create_image(
        readahead_policy="fs",
        parent_image=nydus_scratch_parent_image,
        readahead_files=hint_files_parent.encode(),
    )

    nydus_anchor.mount_overlayfs(
        [nydus_image.rootfs(),
         nydus_scratch_parent_image.rootfs()])

    rafs_conf.enable_rafs_blobcache().set_rafs_backend(Backend.OSS)
    rafs_conf.enable_fs_prefetch()
    rafs_conf.dump_rafs_conf()

    rafs = RafsMount(nydus_anchor, nydus_image, rafs_conf)
    rafs.thread_num(4).mount()

    nc = NydusAPIClient(rafs.get_apisock())
    m = nc.get_blobcache_metrics()
    # TODO: Open this check when prefetch is fixed.
    time.sleep(1)
    assert m["prefetch_data_amount"] != 0

    wg = WorkloadGen(nydus_anchor.mount_point, nydus_anchor.overlayfs)
    wg.setup_workload_generator()

    wg.torture_read(thread_cnt, io_duration)
    wg.finish_torture_read()
Example #15
0
def test_deep_directory(nydus_anchor, rafs_conf: RafsConf,
                        nydus_scratch_image: RafsImage):

    dist = Distributor(nydus_anchor.scratch_dir, 100, 1)
    dist.generate_tree()

    nydus_scratch_image.set_backend(Backend.BACKEND_PROXY).create_image()

    rafs_conf.set_rafs_backend(Backend.BACKEND_PROXY)
    rafs_conf.dump_rafs_conf()

    rafs = RafsMount(nydus_anchor, nydus_scratch_image, rafs_conf)
    rafs.mount()

    wg = WorkloadGen(nydus_anchor.mount_point, nydus_scratch_image.rootfs())

    wg.setup_workload_generator()
    wg.torture_read(8, 5)

    wg.finish_torture_read()
    assert wg.verify_entire_fs()
Example #16
0
def test_hardlink(nydus_anchor: NydusAnchor, nydus_scratch_image,
                  rafs_conf: RafsConf):
    dist = Distributor(nydus_scratch_image.rootfs(), 8, 6)
    dist.generate_tree()

    hardlink_verifier = verifier.HardlinkVerifier(nydus_scratch_image.rootfs(),
                                                  dist)
    hardlink_verifier.scratch()

    nydus_scratch_image.set_backend(Backend.BACKEND_PROXY).create_image()
    rafs_conf.set_rafs_backend(Backend.BACKEND_PROXY)
    rafs = RafsMount(nydus_anchor, nydus_scratch_image, rafs_conf)
    rafs.mount()

    wg = WorkloadGen(nydus_anchor.mount_point, nydus_scratch_image.rootfs())

    hardlink_verifier.verify(nydus_anchor.mount_point,
                             nydus_scratch_image.rootfs())

    wg.setup_workload_generator()
    wg.io_read(3)
    nydus_anchor.check_nydusd_health()

    assert wg.io_error == False
Example #17
0
def test_signal_handling(nydus_anchor: NydusAnchor,
                         nydus_scratch_image: RafsImage, rafs_conf: RafsConf,
                         sig):

    dist = Distributor(nydus_scratch_image.rootfs(), 2, 2)
    dist.generate_tree()
    dist.put_multiple_files(5, Size(2, Unit.KB))

    nydus_scratch_image.set_backend(Backend.BACKEND_PROXY).create_image()

    victim = os.path.join(nydus_anchor.mount_point, dist.files[-1])

    rafs_conf.set_rafs_backend(Backend.BACKEND_PROXY)

    rafs = RafsMount(nydus_anchor, nydus_scratch_image, rafs_conf)
    rafs.mount()
    fd = os.open(victim, os.O_RDONLY)
    assert rafs.is_mounted()
    os.kill(rafs.p.pid, sig)
    time.sleep(3)

    assert not os.path.ismount(nydus_anchor.mount_point)

    rafs.p.wait()
Example #18
0
    try:
        shutil.rmtree(generated_parent_rootfs)
    except FileNotFoundError:
        pass

    os.mkdir(generated_rootfs)
    os.mkdir(generated_parent_rootfs)

    fs_dist = define_fs_structure(dist_define)

    depth = fs_dist["depth"]
    width = fs_dist["width"]
    layers_desc = fs_dist["layers"]

    dist = Distributor(generated_rootfs, depth, width)
    dist.generate_tree()

    for ld in layers_desc:
        with utils.timer("Generating test layer"):
            for d in ld.values():
                for f in d:
                    try:
                        size = f["size"]
                    except KeyError:
                        size = None
                    put_files(dist, f["type"], f["count"], size)

    parent_dist = Distributor(generated_parent_rootfs, depth, width)
    parent_dist.generate_tree()

    for ld in layers_desc:
Example #19
0
def test_backend_swap(nydus_anchor, nydus_scratch_image: RafsImage,
                      rafs_conf: RafsConf):

    dist = Distributor(nydus_scratch_image.rootfs(), 5, 4)
    dist.generate_tree()
    dist.put_multiple_files(100, Size(2, Unit.MB))

    nydus_scratch_image.set_backend(Backend.OSS).create_image(
        readahead_policy="fs", readahead_files="/".encode())
    rafs_conf.set_rafs_backend(
        Backend.OSS).enable_rafs_blobcache().enable_fs_prefetch(
            threads_count=7, bandwidth_rate=Size(2, Unit.MB).B)
    rafs_conf.dump_rafs_conf()

    rafs = RafsMount(nydus_anchor, None, rafs_conf, with_defaults=False)
    rafs.thread_num(4).set_mountpoint(
        nydus_anchor.mount_point).apisock("api_sock").mount()

    nc = NydusAPIClient(rafs.get_apisock())
    nc.pseudo_fs_mount(nydus_scratch_image.bootstrap_path, "/",
                       rafs_conf.path(), None)
    nc.umount_rafs("/")
    assert len(os.listdir(nydus_anchor.mount_point)) == 0

    mp = "/pseudo1"
    nc.pseudo_fs_mount(nydus_scratch_image.bootstrap_path, mp,
                       rafs_conf.path(), None)

    rafs_conf_2nd = RafsConf(nydus_anchor, nydus_scratch_image)
    rafs_conf_2nd.set_rafs_backend(
        Backend.LOCALFS,
        image=nydus_scratch_image).enable_rafs_blobcache().enable_fs_prefetch(
            threads_count=3, bandwidth_rate=Size(1, Unit.MB).B)
    rafs_conf_2nd.dump_rafs_conf()

    new_image = (RafsImage(
        nydus_anchor, nydus_scratch_image.rootfs()).set_backend(
            Backend.LOCALFS).create_image(readahead_policy="fs",
                                          readahead_files="/".encode()))

    # TODO: Once upon a time, more than one fd are open. Check why this happens.
    wg = WorkloadGen(
        os.path.join(nydus_anchor.mount_point, mp.strip("/")),
        nydus_scratch_image.rootfs(),
    )

    wg.setup_workload_generator()
    wg.torture_read(8, 8)

    for i in range(1, 50):
        logging.debug("swap for the %dth time", i)
        nc.swap_backend(mp, new_image.bootstrap_name, rafs_conf_2nd.path())
        # assert nc.get_blobcache_metrics(mp)["prefetch_workers"] == 3
        time.sleep(0.2)
        nc.swap_backend(mp, nydus_scratch_image.bootstrap_name,
                        rafs_conf.path())
        utils.clean_pagecache()

    wg.finish_torture_read()

    assert wg.io_error == False

    nc.umount_rafs(mp)
    utils.clean_pagecache()
Example #20
0
def test_whiteout(nydus_anchor, rafs_conf, whiteout_spec):
    _td_1 = tempfile.TemporaryDirectory(dir=nydus_anchor.workspace)
    _td_2 = tempfile.TemporaryDirectory(dir=nydus_anchor.workspace)
    parent_rootfs = _td_1.name
    upper_rootfs = _td_2.name

    whiteout = Whiteout(whiteout_spec)

    parent_image = RafsImage(nydus_anchor, parent_rootfs, "parent_bs",
                             "parent_blob")

    dist_parent = Distributor(parent_rootfs, 6, 4)
    dist_parent.generate_tree()
    dist_parent.put_directories(20)
    dist_parent.put_multiple_files(50, Size(32, Unit.KB))
    dist_parent.put_symlinks(30)
    dist_parent.put_hardlinks(20)

    to_be_removed = dist_parent.put_single_file(Size(7, Unit.KB))

    layered_image = RafsImage(nydus_anchor, upper_rootfs, "bs", "blob")

    dist_upper = Distributor(upper_rootfs, 3, 5)
    dist_upper.generate_tree()
    dist_upper.put_multiple_files(27, Size(3, Unit.MB))
    dist_upper.put_symlinks(5)

    # `to_be_removed` should look like `a/b/c`
    whiteout.whiteout_one_file(upper_rootfs, to_be_removed)
    # Put a whiteout file that does not hide any file from lower layer
    whiteout.whiteout_one_file(upper_rootfs, "i/am/troublemaker/foo")

    dir_to_be_whiteout_opaque = dist_parent.dirs[randint(
        0,
        len(dist_parent.dirs) - 1)]
    # `dir_to_be_removed` should look like `a/b/c`
    whiteout.whiteout_opaque_directory(upper_rootfs, dir_to_be_whiteout_opaque)

    dist_parent.put_directories(1)
    dir_to_be_removed = dist_parent.dirs[-1]
    whiteout.whiteout_one_dir(upper_rootfs, dir_to_be_removed)

    parent_image.set_backend(Backend.OSS).create_image()
    layered_image.set_backend(
        Backend.OSS).whiteout_spec(whiteout_spec).create_image(
            parent_image=parent_image)

    rafs_conf.set_rafs_backend(Backend.OSS)

    nydus_anchor.mount_overlayfs(
        [layered_image.rootfs(), parent_image.rootfs()])
    rafs = RafsMount(nydus_anchor, layered_image, rafs_conf)
    rafs.mount()

    wg = WorkloadGen(nydus_anchor.mount_point, nydus_anchor.overlayfs)

    assert not os.path.exists(
        os.path.join(nydus_anchor.mount_point, to_be_removed))
    assert not os.path.exists(
        os.path.join(nydus_anchor.mount_point, dir_to_be_removed))

    files_under_opaque_dir = os.listdir(
        os.path.join(nydus_anchor.mount_point, dir_to_be_whiteout_opaque))

    # If opaque dir has files, only file from lower layer will be hidden.
    if len(files_under_opaque_dir) != 0:
        upper_files = os.listdir(
            os.path.join(upper_rootfs, dir_to_be_whiteout_opaque))
        for f in files_under_opaque_dir:
            assert f in upper_files

    assert wg.verify_entire_fs()
Example #21
0
def test_stargz(
    nydus_anchor: NydusAnchor,
    rafs_conf: RafsConf,
    nydus_scratch_image: RafsImage,
):
    """
    Example command:
        stargzify file:`pwd`/foo.tar.gz foo.stargz

    """
    intermediator = "tmp.tar.gz"
    stargz_image = "tmp.stargz"

    dist = Distributor(nydus_scratch_image.rootfs(), 4, 4)
    dist.generate_tree()
    dirs = dist.put_directories(20)
    dist.put_multiple_files(100, Size(64, Unit.KB))
    dist.put_symlinks(30)
    dist.put_multiple_files(10, Size(4, Unit.MB))
    dist.put_hardlinks(20)
    dist.put_single_file(Size(3, Unit.MB), name="test")
    try:
        shutil.rmtree("origin")
    except Exception:
        pass
    shutil.copytree(nydus_scratch_image.rootfs(), "origin", symlinks=True)
    utils.write_tar_gz(nydus_scratch_image.rootfs(), intermediator)

    cmd = ["framework/bin/stargzify", f"file:{intermediator}", stargz_image]
    utils.execute(cmd)

    toc = utils.parse_stargz(stargz_image)
    image = RafsImage(
        nydus_anchor,
        toc,
        "bootstrap_scratched",
        "blob_scratched",
        clear_from_oss=True,
    )

    # This is a trick since blob name is usually a temp file created when RafsImage instantiated.
    # framework will upload stargz to oss.
    image.blob_abs_path = stargz_image
    image.set_backend(Backend.OSS).set_param(
        "blob-id", uuid.uuid4()).create_image(from_stargz=True)

    rafs_conf.set_rafs_backend(Backend.OSS)
    rafs_conf.enable_rafs_blobcache(is_compressed=True)

    rafs = RafsMount(nydus_anchor, image, rafs_conf)
    rafs.mount()

    wg = WorkloadGen(nydus_anchor.mount_point, "origin")

    wg.verify_entire_fs()

    wg.setup_workload_generator()
    wg.torture_read(4, 4)

    wg.finish_torture_read()
    assert not wg.io_error
Example #22
0
def test_prefetch_with_cache(
    nydus_anchor,
    nydus_scratch_image: RafsImage,
    rafs_conf: RafsConf,
    thread_cnt,
    compressor,
    is_cache_compressed,
    converter,
    items,
):
    """
    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.
    """

    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_multiple_files(10, Size(5, 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.LOCALFS).create_image(
        image_bin=converter,
        compressor=compressor,
        readahead_policy="fs",
        readahead_files="/".encode(),
    )

    rafs_conf.enable_rafs_blobcache(
        is_compressed=is_cache_compressed).enable_fs_prefetch()
    rafs_conf.set_rafs_backend(Backend.LOCALFS, image=nydus_scratch_image)

    if len(items) > 0:
        for i in items:
            item = RafsConf.__dict__[i]
            item(rafs_conf)

    rafs = RafsMount(nydus_anchor, nydus_scratch_image, rafs_conf)
    rafs.thread_num(6).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.verify_entire_fs()

    workload_gen.setup_workload_generator()
    workload_gen.torture_read(thread_cnt, 6)

    assert NydusAnchor.check_nydusd_health()

    workload_gen.finish_torture_read()
    assert not workload_gen.io_error
Example #23
0
def test_pseudo_fs(nydus_anchor, nydus_image, rafs_conf: RafsConf):
    nydus_image.set_backend(Backend.BACKEND_PROXY).create_image()

    rafs_conf.set_rafs_backend(Backend.BACKEND_PROXY)

    rafs = RafsMount(nydus_anchor, None, rafs_conf)
    rafs.mount()
    time.sleep(1)
    nc = NydusAPIClient(rafs.get_apisock())

    try:
        shutil.rmtree("pseudo_fs_scratch")
    except FileNotFoundError:
        pass

    scratch_rootfs = shutil.copytree(nydus_image.rootfs(),
                                     "pseudo_fs_scratch",
                                     symlinks=True)
    dist = Distributor(scratch_rootfs, 5, 5)
    dist.generate_tree()
    dist.put_multiple_files(20, Size(8, Unit.KB))

    ###
    suffix = "1"
    image = RafsImage(
        nydus_anchor,
        scratch_rootfs,
        "bs" + suffix,
        "blob" + suffix,
    )
    conf = RafsConf(nydus_anchor)
    conf.enable_fs_prefetch()
    conf.enable_validation()
    conf.set_rafs_backend(Backend.BACKEND_PROXY)
    conf.dump_rafs_conf()

    image.set_backend(Backend.BACKEND_PROXY).create_image()
    nc.pseudo_fs_mount(image.bootstrap_path, f"/pseudo{suffix}", conf.path(),
                       None)
    ###
    suffix = "2"
    image = RafsImage(
        nydus_anchor,
        scratch_rootfs,
        "bs" + suffix,
        "blob" + suffix,
    )
    conf = RafsConf(nydus_anchor)
    conf.enable_rafs_blobcache()
    conf.enable_validation()
    conf.enable_records_readahead()
    conf.set_rafs_backend(Backend.BACKEND_PROXY)
    conf.dump_rafs_conf()

    dist.put_multiple_files(20, Size(8, Unit.KB))

    image.set_backend(Backend.BACKEND_PROXY).create_image()
    nc.pseudo_fs_mount(image.bootstrap_path, f"/pseudo{suffix}", conf.path(),
                       None)
    ###
    suffix = "3"
    image = RafsImage(
        nydus_anchor,
        scratch_rootfs,
        "bs" + suffix,
        "blob" + suffix,
    )
    conf = RafsConf(nydus_anchor)
    conf.enable_rafs_blobcache()
    conf.enable_records_readahead()
    conf.set_rafs_backend(Backend.BACKEND_PROXY)
    conf.dump_rafs_conf()

    dist.put_multiple_files(20, Size(8, Unit.KB))

    image.set_backend(Backend.BACKEND_PROXY).create_image()
    nc.pseudo_fs_mount(image.bootstrap_path, f"/pseudo{suffix}", conf.path(),
                       None)

    wg1 = WorkloadGen(os.path.join(nydus_anchor.mount_point, "pseudo1"),
                      scratch_rootfs)
    wg2 = WorkloadGen(os.path.join(nydus_anchor.mount_point, "pseudo2"),
                      scratch_rootfs)
    wg3 = WorkloadGen(os.path.join(nydus_anchor.mount_point, "pseudo3"),
                      scratch_rootfs)

    time.sleep(2)
    wg1.setup_workload_generator()
    wg2.setup_workload_generator()
    wg3.setup_workload_generator()

    wg1.torture_read(4, 8)
    wg2.torture_read(4, 8)
    wg3.torture_read(4, 8)

    wg1.finish_torture_read()
    wg2.finish_torture_read()
    wg3.finish_torture_read()

    # TODO: Temporarily disable the verification as hard to select `verify dir`
    # assert wg1.verify_entire_fs()
    # assert wg2.verify_entire_fs()
    # assert wg3.verify_entire_fs()

    nc.umount_rafs("/pseudo1")
    nc.umount_rafs("/pseudo2")
    nc.umount_rafs("/pseudo3")