class BlockdevIncbkXptAllocDepth(BlockdevLiveBackupBaseTest): """Allocation depth export test""" def __init__(self, test, params, env): super(BlockdevIncbkXptAllocDepth, self).__init__(test, params, env) self._base_image, self._snapshot_image = self.params.objects( 'image_backup_chain') localhost = socket.gethostname() self.params['nbd_server'] = localhost if localhost else 'localhost' self._nbd_image_obj = self.source_disk_define_by_params( self.params, self.params['nbd_image_tag']) self._block_export_uid = self.params.get('block_export_uid') self._nbd_export = None self._is_exported = False def _init_nbd_export(self, tag): self._nbd_export = InternalNBDExportImage( self.main_vm, self.params, tag) if self._block_export_uid else QemuNBDExportImage( self.params, tag) def _start_nbd_export(self, tag): if self._block_export_uid is not None: # export local image with block-export-add self._nbd_export.start_nbd_server() self._nbd_export.add_nbd_image('drive_%s' % tag) else: # export local image with qemu-nbd # we should stop vm and rebase sn onto base if self.main_vm.is_alive(): self.main_vm.destroy() self._rebase_sn_onto_base() self._nbd_export.export_image() self._is_exported = True def _rebase_sn_onto_base(self): disk = self.source_disk_define_by_params(self.params, self._snapshot_image) disk.rebase(params=self.params) def post_test(self): self.stop_export() super(BlockdevIncbkXptAllocDepth, self).post_test() def stop_export(self): """stop nbd export""" if self._is_exported: self._nbd_export.stop_export() self._is_exported = False def export_image(self, tag): """export image from nbd server""" self._init_nbd_export(tag) self._start_nbd_export(tag) def check_allocation_depth_from_export(self, zero, data): """ check allocation depth from output of qemu-img map local(base image): zero: false, data: false backing(snapshot): zero: true, data: true """ opts = filename_to_file_opts(self._nbd_image_obj.image_filename) opts[self.params['dirty_bitmap_opt']] = 'qemu:allocation-depth' map_cmd = '{qemu_img} map --output=json {args}'.format( qemu_img=get_qemu_img_binary(self.params), args="'json:%s'" % json.dumps(opts)) result = process.run(map_cmd, ignore_status=False, shell=True) for item in json.loads(result.stdout.decode().strip()): if item['zero'] is zero and item['data'] is data: break else: self.test.fail('Failed to get "zero": %s, "data": %s' % (zero, data)) def do_test(self): self.do_full_backup() self.export_image(self._base_image) self.check_allocation_depth_from_export(zero=False, data=False) self.stop_export() self.export_image(self._snapshot_image) self.check_allocation_depth_from_export(zero=True, data=True)
class BlockdevIncbkXptMutBitmaps(BlockdevLiveBackupBaseTest): """Multiple bitmaps export test""" def __init__(self, test, params, env): super(BlockdevIncbkXptMutBitmaps, self).__init__(test, params, env) self._bitmaps = params.objects('bitmap_list') self._bitmap_states = [True, False] localhost = socket.gethostname() self.params['nbd_server'] = localhost if localhost else 'localhost' self._nbd_image_obj = self.source_disk_define_by_params( self.params, self.params['nbd_image_tag']) self._block_export_uid = self.params.get('block_export_uid') self._nbd_export = None self._is_exported = False def _init_nbd_export(self): self._nbd_export = InternalNBDExportImage( self.main_vm, self.params, self._full_bk_images[0] ) if self._block_export_uid else QemuNBDExportImage( self.params, self._full_bk_images[0]) def check_nbd_export_info(self): if self._block_export_uid is not None: info = self._nbd_export.query_nbd_export() if info is None: self.test.fail('Failed to get the nbd block export') if (not info or info['shutting-down'] or info['id'] != self._block_export_uid or info['type'] != 'nbd' or info['node-name'] != self._full_bk_nodes[0]): self.test.fail( 'Failed to get the correct export information: %s' % info) def do_nbd_export(self): if self._block_export_uid is not None: self._nbd_export.start_nbd_server() self._nbd_export.add_nbd_image(self._full_bk_nodes[0]) else: self.main_vm.destroy() self._nbd_export.export_image() self._is_exported = True def prepare_test(self): self.prepare_main_vm() self.add_target_data_disks() self._init_nbd_export() def post_test(self): if self._is_exported: self._nbd_export.stop_export() super(BlockdevIncbkXptMutBitmaps, self).post_test() def add_persistent_bitmaps(self): """Add two bitmaps, one is enabled while the other is disabled""" bitmaps = [{ 'node': self._full_bk_nodes[0], 'name': b, 'persistent': True, 'disabled': s } for b, s in zip(self._bitmaps, self._bitmap_states)] job_list = [{ 'type': 'block-dirty-bitmap-add', 'data': data } for data in bitmaps] self.main_vm.monitor.transaction(job_list) def check_bitmaps_from_export(self): qemu_img = get_qemu_img_binary(self.params) opts = filename_to_file_opts(self._nbd_image_obj.image_filename) for bm in self._bitmaps: opts[self.params['dirty_bitmap_opt']] = 'qemu:dirty-bitmap:%s' % bm args = "'json:%s'" % json.dumps(opts) map_cmd = '{qemu_img} map --output=human {args}'.format( qemu_img=qemu_img, args=args) result = process.run(map_cmd, ignore_status=False, shell=True) if self._nbd_image_obj.image_filename not in result.stdout_text: self.test.fail('Failed to get bitmap info.') def do_test(self): self.add_persistent_bitmaps() self.do_nbd_export() self.check_nbd_export_info() self.check_bitmaps_from_export()