Exemplo n.º 1
0
def test_backing_chain(tmpdir):
    size = 128 * 1024
    base = str(tmpdir.join("base.raw"))
    top = str(tmpdir.join("top.qcow2"))

    base_data = b"data from base".ljust(32, b"\0")

    # Add base image with some data.
    qemu_img.create(base, "raw", size=size)
    with qemu_nbd.open(base, "raw") as c:
        c.write(0, base_data)
        c.flush()

    # Add empty overlay.
    qemu_img.create(top, "qcow2", backing_file=base, backing_format="raw")

    top_addr = nbd.UnixAddress(str(tmpdir.join("sock")))

    # By default, we see data from base.
    with qemu_nbd.run(top, "qcow2", top_addr), \
            nbd.Client(top_addr) as c:
        assert c.read(0, 32) == base_data

    # With backing chain disabled, we see data only from top.
    with qemu_nbd.run(top, "qcow2", top_addr, backing_chain=False), \
            nbd.Client(top_addr) as c:
        assert c.read(0, 32) == b"\0" * 32
Exemplo n.º 2
0
def test_options(tmpdir, fmt, options):
    size = 4 * 1024**2
    chunk_size = 128 * 1024

    src = str(tmpdir.join("src." + fmt))
    qemu_img.create(src, fmt, size=size)

    with qemu_nbd.open(src, fmt) as c:
        for offset in range(0, size, chunk_size):
            c.write(offset, struct.pack(">Q", offset))
        c.flush()

    dst = str(tmpdir.join("dst." + fmt))
    qemu_img.create(dst, fmt, size=size)

    src_addr = nbd.UnixAddress(str(tmpdir.join("src.sock")))
    dst_addr = nbd.UnixAddress(str(tmpdir.join("dst.sock")))

    with qemu_nbd.run(
                src, fmt, src_addr,
                read_only=True,
                **options), \
            qemu_nbd.run(
                dst, fmt, dst_addr,
                **options), \
            nbd.Client(src_addr) as src_client, \
            nbd.Client(dst_addr) as dst_client:

        nbdutil.copy(src_client, dst_client)

    qemu_img.compare(src, dst)
Exemplo n.º 3
0
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)
Exemplo n.º 4
0
def test_shared(tmpdir, fmt):
    size = 1024**2
    chunk_size = size // 2

    src = str(tmpdir.join("src." + fmt))
    qemu_img.create(src, fmt, size=size)

    with qemu_nbd.open(src, fmt) as c:
        c.write(0, b"a" * chunk_size)
        c.write(0, b"b" * chunk_size)
        c.flush()

    dst = str(tmpdir.join("dst." + fmt))
    qemu_img.create(dst, fmt, size=size)

    src_addr = nbd.UnixAddress(str(tmpdir.join("src.sock")))
    dst_addr = nbd.UnixAddress(str(tmpdir.join("dst.sock")))

    # Start 2 qemu-nbd servers, each with 2 clients that can read and write in
    # parallel for higher throughput.

    with qemu_nbd.run(src, fmt, src_addr, read_only=True, shared=2), \
            qemu_nbd.run(dst, fmt, dst_addr, shared=2), \
            nbd.Client(src_addr) as src_client1, \
            nbd.Client(src_addr) as src_client2, \
            nbd.Client(dst_addr) as dst_client1, \
            nbd.Client(dst_addr) as dst_client2:

        # Copy first half of the image with src_client1 and dst_client2 and
        # second half with src_client2 and dst_client2. In a real application
        # we would have more clients, running in multiple threads.

        chunk1 = src_client1.read(0, chunk_size)
        dst_client1.write(0, chunk1)

        chunk2 = src_client2.read(chunk_size, chunk_size)
        dst_client2.write(chunk_size, chunk2)

        dst_client1.flush()
        dst_client2.flush()

    qemu_img.compare(src, dst)
Exemplo n.º 5
0
def test_run_tcp(tmpfile):
    with io.open(tmpfile, "r+b") as f:
        f.truncate(1024**2)

    addr = nbd.TCPAddress("localhost", testutil.random_tcp_port())

    with qemu_nbd.run(tmpfile, "raw", addr):
        # The helper already waited for the NBD socket, not wait needed.
        assert sockutil.wait_for_socket(addr, 0.0)

    # The socket must be closed, no wait needed.
    assert not sockutil.wait_for_socket(addr, 0.0)
Exemplo n.º 6
0
def test_open_tcp(tmpdir, url_template, host, export):
    image = str(tmpdir.join("image"))
    with open(image, "wb") as f:
        f.truncate(1024**3)

    sock = nbd.TCPAddress(host, testutil.random_tcp_port())
    url = url_template.format(port=sock.port)

    log.debug("Trying url=%r export=%r", url, export)
    with qemu_nbd.run(image, "raw", sock, export_name=export):
        with nbd.open(urlparse(url)) as c:
            assert c.export_size == 1024**3
Exemplo n.º 7
0
def test_open_unix(tmpdir, url, export):
    image = str(tmpdir.join("image"))
    with open(image, "wb") as f:
        f.truncate(1024**3)

    sock = nbd.UnixAddress(tmpdir.join("sock"))
    url = url.replace("/path", sock)

    log.debug("Trying url=%r export=%r", url, export)
    with qemu_nbd.run(image, "raw", sock, export_name=export):
        with nbd.open(urlparse(url)) as c:
            assert c.export_size == 1024**3
Exemplo n.º 8
0
def test_qcow2_write_read(tmpdir):
    image = str(tmpdir.join("image"))
    sock = nbd.UnixAddress(tmpdir.join("sock"))
    offset = 1024**2
    data = b"can read and write qcow2"
    create_image(image, "qcow2", 1024**3)

    with qemu_nbd.run(image, "qcow2", sock):
        with nbd.Client(sock) as c:
            c.write(offset, data)
            c.flush()

        with nbd.Client(sock) as c:
            assert c.read(offset, len(data)) == data
Exemplo n.º 9
0
def test_raw_read(tmpdir):
    image = str(tmpdir.join("image"))
    sock = nbd.UnixAddress(tmpdir.join("sock"))
    offset = 1024**2
    data = b"can read from raw"

    with open(image, "wb") as f:
        f.truncate(1024**3)
        f.seek(offset)
        f.write(data)

    with qemu_nbd.run(image, "raw", sock):
        with nbd.Client(sock) as c:
            assert c.read(offset, len(data)) == data
Exemplo n.º 10
0
def test_run_unix(tmpdir):
    image = str(tmpdir.join("image"))
    sock = str(tmpdir.join("sock"))

    with io.open(image, "wb") as f:
        f.truncate(1024**2)

    addr = nbd.UnixAddress(sock)

    with qemu_nbd.run(image, "raw", addr):
        # The helper already waited for the NBD socket, not wait needed.
        assert sockutil.wait_for_socket(addr, 0.0)

    # The socket must be closed, no wait needed.
    assert not sockutil.wait_for_socket(addr, 0.0)
Exemplo n.º 11
0
def test_raw_write(tmpdir):
    image = str(tmpdir.join("image"))
    with open(image, "wb") as f:
        f.truncate(1024**3)
    sock = nbd.UnixAddress(tmpdir.join("sock"))
    offset = 1024**2
    data = b"can write to raw"

    with qemu_nbd.run(image, "raw", sock):
        with nbd.Client(sock) as c:
            c.write(offset, data)
            c.flush()

    with open(image, "rb") as f:
        f.seek(offset)
        assert f.read(len(data)) == data
Exemplo n.º 12
0
def test_handshake(tmpdir, export, fmt):
    image = str(tmpdir.join("image"))
    create_image(image, fmt, 1024**3)
    sock = nbd.UnixAddress(tmpdir.join("sock"))

    with qemu_nbd.run(image, fmt, sock, export_name=export):
        if export:
            c = nbd.Client(sock, export)
        else:
            c = nbd.Client(sock)
        with c:
            # TODO: test transmission_flags?
            assert c.export_size == 1024**3
            assert c.minimum_block_size == 1
            assert c.preferred_block_size == 4096
            assert c.maximum_block_size == 32 * 1024**2
            assert c.base_allocation
Exemplo n.º 13
0
def test_handshake(tmpdir, export, fmt):
    image = str(tmpdir.join("image"))
    create_image(image, fmt, 1024**3)
    sock = nbd.UnixAddress(tmpdir.join("sock"))

    with qemu_nbd.run(image, fmt, sock, export_name=export):
        if export:
            c = nbd.Client(sock, export)
        else:
            c = nbd.Client(sock)
        with c:
            # TODO: test transmission_flags?
            assert c.export_size == 1024**3
            assert c.minimum_block_size == 1
            assert c.preferred_block_size == 4096
            assert c.maximum_block_size == 32 * 1024**2
            # Both available in in current qemu-nbd (>= 5.2.0).
            assert c.has_base_allocation
            assert c.has_allocation_depth == (fmt != "raw")
Exemplo n.º 14
0
def test_zero_min_block_size(tmpdir, fmt):
    offset = 1024**2
    image = str(tmpdir.join("image"))
    sock = nbd.UnixAddress(tmpdir.join("sock"))
    create_image(image, fmt, 1024**3)

    with qemu_nbd.run(image, fmt, sock):
        # Fill range with data
        with nbd.Client(sock) as c:
            size = c.minimum_block_size
            c.write(offset, b"x" * size)
            c.flush()

        # Zero range using minimum block size
        with nbd.Client(sock) as c:
            c.zero(offset, size)
            c.flush()

        with nbd.Client(sock) as c:
            assert c.read(offset, size) == b"\0" * size
Exemplo n.º 15
0
def test_zero(tmpdir, fmt):
    size = 2 * 1024**2
    offset = 1024**2
    image = str(tmpdir.join("image"))
    sock = nbd.UnixAddress(tmpdir.join("sock"))
    create_image(image, fmt, size)

    with qemu_nbd.run(image, fmt, sock):
        # Fill image with data
        with nbd.Client(sock) as c:
            c.write(0, b"x" * size)
            c.flush()

        # Zero a range
        with nbd.Client(sock) as c:
            c.zero(offset, 4096)
            c.flush()

        with nbd.Client(sock) as c:
            assert c.read(offset, 4096) == b"\0" * 4096