def test_base_allocation_many_extents(nbd_server, user_file): # Tested only with raw since qcow2 minimal extent is cluster size (64K), # and writing 1000 extents (62.5 MiB) will be too slow in the CI. # Extents must be multiple of file system block size. extent_length = os.statvfs(user_file.path).f_bsize # Use number which is not a multiple of our buffer capacity (1024 extents) # to ensure we read partial buffers correctly. extents_count = 2000 size = extents_count * extent_length create_image(user_file.path, "raw", size) nbd_server.image = user_file.path nbd_server.fmt = "raw" nbd_server.start() with nbd.open(nbd_server.url) as c: # Write data to all even extents. data = b"x" * extent_length for i in range(0, size, extent_length * 2): c.write(i, data) extents = list(nbdutil.extents(c)) assert len(extents) == extents_count for i, ext in enumerate(extents): assert ext.length == extent_length assert ext.zero == bool(i % 2)
def test_base_allocation_some_data(nbd_server, user_file, fmt, zero_flags): size = 1024**3 create_image(user_file.path, fmt, size) nbd_server.image = user_file.path nbd_server.fmt = fmt nbd_server.start() # Use qcow2 cluster size to avoid inconsistent results on CentOS and # Fedora. data_length = 64 * 1024 zero_length = size // 2 - data_length with nbd.open(nbd_server.url) as c: # Create 4 extents: data, zero, data, zero. c.write(0, b"x" * data_length) c.write(size // 2, b"x" * data_length) extents = list(nbdutil.extents(c)) assert extents == [ nbd.Extent(length=data_length, flags=0), nbd.Extent(length=zero_length, flags=zero_flags), nbd.Extent(length=data_length, flags=0), nbd.Extent(length=zero_length, flags=zero_flags), ]
def test_some_data_offset_unaligned(dirty): c = SomeData(1, dirty) extents = list( nbdutil.extents(c, offset=c.extent_size // 2 * 3, dirty=dirty)) assert extents == [ nbd.Extent(c.extent_size // 2, 1), nbd.Extent(c.extent_size, 0), ]
def test_some_data_offset(dirty): c = SomeData(1, dirty) extents = list(nbdutil.extents(c, offset=0, dirty=dirty)) assert extents == [ nbd.Extent(c.extent_size, 0), nbd.Extent(c.extent_size, 1), nbd.Extent(c.extent_size, 0), ]
def verify_full_backup(sock, export_name): with nbd.Client(sock, export_name) as c: log.debug("Backing up data with nbd client") offset = 0 for ext in nbdutil.extents(c): if not ext.zero: expected = b"%d\n" % offset data = c.read(offset, len(expected)) assert data == expected offset += ext.length
def test_base_allocation_some_data_unaligned(nbd_server, user_file, fmt, zero_flags): size = 1024**2 create_image(user_file.path, fmt, size) nbd_server.image = user_file.path nbd_server.fmt = fmt nbd_server.start() data_length = 64 * 1024 data_offset = 2 * data_length with nbd.open(nbd_server.url) as c: # Create 3 extents: zero, data, zero. c.write(data_offset, b"x" * data_length) # Unaligned part from first extent and last extent. extents = list(nbdutil.extents(c, data_offset - 1, data_length + 2)) assert extents == [ nbd.Extent(length=1, flags=zero_flags), nbd.Extent(length=data_length, flags=0), nbd.Extent(length=1, flags=zero_flags), ] # Unaligned part from second extent. extents = list(nbdutil.extents(c, data_offset + 1, data_length - 2)) assert extents == [ nbd.Extent(length=data_length - 2, flags=0), ] # Unaligned part from second and last extents. extents = list(nbdutil.extents(c, data_offset + 1, data_length)) assert extents == [ nbd.Extent(length=data_length - 1, flags=0), nbd.Extent(length=1, flags=zero_flags), ]
def copy_dirty(nbd_url, backup_disk): log.info("Backing up dirty extents from %s to %s", nbd_url, backup_disk) backup_url = urlparse(nbd_url) with nbd.open(backup_url, dirty=True) as src_client, \ qemu_nbd.open(backup_disk, "qcow2") as dst_client: buf = bytearray(4 * 1024**2) offset = 0 for ext in nbdutil.extents(src_client, dirty=True): if ext.dirty: todo = ext.length while todo: step = min(todo, len(buf)) view = memoryview(buf)[:step] src_client.readinto(offset, view) dst_client.write(offset, view) offset += step todo -= step else: offset += ext.length
def test_last_extent_exceeds_length(dirty, offset, length): c = ExcceedsLength(1, dirty) extents = list( nbdutil.extents(c, offset=offset, length=length, dirty=dirty)) assert extents == [nbd.Extent(length, 1)]
def test_short_reply_offset(dirty, offset): c = ShortReply(1, dirty) extents = list(nbdutil.extents(c, offset=offset, dirty=dirty)) assert extents == [nbd.Extent(c.export_size - offset, 1)]
def test_short_reply_offset_length(dirty, offset, length): c = ShortReply(1, dirty) extents = list( nbdutil.extents(c, offset=offset, length=length, dirty=dirty)) assert extents == [nbd.Extent(length, 1)]
def test_short_reply(dirty): c = ShortReply(1, dirty) extents = list(nbdutil.extents(c, dirty=dirty)) assert extents == [nbd.Extent(c.export_size, 1)]
def test_single_extent_offset_length(dirty, offset, length): c = SingleExtent(1, dirty) extents = list( nbdutil.extents(c, offset=offset, length=length, dirty=dirty)) assert extents == [nbd.Extent(length, 1)]
def test_single_extent_offset(dirty, offset): c = SingleExtent(1, dirty) extents = list(nbdutil.extents(c, offset=offset, dirty=dirty)) assert extents == [nbd.Extent(c.export_size - offset, 1)]
def test_single_extent(dirty): c = SingleExtent(1, dirty) extents = list(nbdutil.extents(c, dirty=dirty)) assert extents == [nbd.Extent(c.export_size, 1)]
def test_complete_reply(dirty): c = CompleteReply(1, dirty) extents = list(nbdutil.extents(c, dirty=dirty)) assert extents == [nbd.Extent(c.export_size, 1)]