def test_copy_nbd_to_nbd(tmpdir, src_fmt, dst_fmt, zero, hole): # Default cluser size with qcow2 format. cluster_size = 64 * 1024 extents = [ ("data", cluster_size), ("zero", cluster_size), ("data", cluster_size), ("hole", cluster_size + io.MAX_ZERO_SIZE), ("data", cluster_size + io.BUFFER_SIZE), ("hole", cluster_size), ("data", cluster_size), ] size = sum(length for _, length in extents) src = str(tmpdir.join("src." + src_fmt)) qemu_img.create(src, src_fmt, size=size) populate_image(src, src_fmt, extents) src_sock = UnixAddress(tmpdir.join("src.sock")) src_url = urlparse(src_sock.url()) dst = str(tmpdir.join("dst." + dst_fmt)) qemu_img.create(dst, dst_fmt, size=size) dst_sock = UnixAddress(tmpdir.join("dst.sock")) dst_url = urlparse(dst_sock.url()) # Note: We need extra worker for reading extents for source. max_workers = 2 with qemu_nbd.run( src, src_fmt, src_sock, read_only=True, shared=max_workers + 1), \ qemu_nbd.run( dst, dst_fmt, dst_sock, shared=max_workers), \ nbd.open(src_url, "r") as src_backend, \ nbd.open(dst_url, "r+", sparse=True) as dst_backend: # Because we copy to new image, we can always use zero=False, but we # test both to verify that the result is the same. io.copy(src_backend, dst_backend, max_workers=max_workers, zero=zero, hole=hole) # Compare image content - must match. qemu_img.compare(src, dst) # Allocation can be compared only with qcow2 images when we write zeroes to # zero extents and skip holes. if src_fmt == "qcow2" and dst_fmt == "qcow2" and zero and not hole: qemu_img.compare(src, dst, strict=True)
def test_copy_dirty(progress): src = memory.Backend( mode="r", data=create_backing("ABCD"), extents={"dirty": create_dirty_extents("AbCd")}, ) dst_backing = create_backing("0000") dst = memory.Backend("r+", data=dst_backing) io.copy(src, dst, dirty=True, max_workers=1, progress=progress) # Copy dirty extents, skip clean extents. assert dst_backing == create_backing("A0C0")
def test_copy_dirty_progress(): src = memory.Backend( mode="r", data=create_backing("A0C-"), extents={"dirty": create_zero_extents("A0C-")}, ) dst_backing = create_backing("0000") dst = memory.Backend("r+", data=dst_backing) p = FakeProgress() io.copy(src, dst, dirty=True, max_workers=1, progress=p) # Report at least every extent. assert len(p.updates) >= 4 # Report entire image size. assert sum(p.updates) == len(dst_backing)
def test_copy_write_to(buffer_size, zero, hole, progress): src_extents = create_zero_extents("B0-") src_backing = create_backing("B0-") dst_backing = create_backing( "AAA" if zero and hole else "AA0" if zero else "A00") src = memory.WriterTo(mode="r", data=src_backing, extents={"zero": src_extents}) dst = memory.Backend("r+", data=dst_backing) io.copy(src, dst, max_workers=1, buffer_size=buffer_size, zero=zero, hole=hole, progress=progress) assert dst_backing == src_backing
def test_reraise_src_error(): src = FailingBackend(fail_read=True) dst = FailingBackend() with pytest.raises(BackendError) as e: io.copy(src, dst) assert str(e.value) == "read error"
def test_reraise_dst_error(): src = FailingBackend() dst = FailingBackend(fail_write=True) with pytest.raises(BackendError) as e: io.copy(src, dst) assert str(e.value) == "write error"