1#!/usr/bin/env python3 2# 3# Test incremental/backup across iothread contexts 4# 5# Copyright (c) 2019 John Snow for Red Hat, Inc. 6# 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 2 of the License, or 10# (at your option) any later version. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program. If not, see <http://www.gnu.org/licenses/>. 19# 20# owner=jsnow@redhat.com 21 22import os 23import iotests 24from iotests import log 25 26iotests.verify_image_format(supported_fmts=['qcow2']) 27size = 64 * 1024 * 1024 28 29with iotests.FilePath('img0') as img0_path, \ 30 iotests.FilePath('img1') as img1_path, \ 31 iotests.FilePath('img0-full') as img0_full_path, \ 32 iotests.FilePath('img1-full') as img1_full_path, \ 33 iotests.FilePath('img0-incr') as img0_incr_path, \ 34 iotests.FilePath('img1-incr') as img1_incr_path, \ 35 iotests.VM() as vm: 36 37 def create_target(filepath, name, size): 38 basename = os.path.basename(filepath) 39 nodename = "file_{}".format(basename) 40 log(vm.command('blockdev-create', job_id='job1', 41 options={ 42 'driver': 'file', 43 'filename': filepath, 44 'size': 0, 45 })) 46 vm.run_job('job1') 47 log(vm.command('blockdev-add', driver='file', 48 node_name=nodename, filename=filepath)) 49 log(vm.command('blockdev-create', job_id='job2', 50 options={ 51 'driver': iotests.imgfmt, 52 'file': nodename, 53 'size': size, 54 })) 55 vm.run_job('job2') 56 log(vm.command('blockdev-add', driver=iotests.imgfmt, 57 node_name=name, 58 file=nodename)) 59 60 log('--- Preparing images & VM ---\n') 61 vm.add_object('iothread,id=iothread0') 62 vm.add_object('iothread,id=iothread1') 63 vm.add_device('virtio-scsi-pci,id=scsi0,iothread=iothread0') 64 vm.add_device('virtio-scsi-pci,id=scsi1,iothread=iothread1') 65 iotests.qemu_img_create('-f', iotests.imgfmt, img0_path, str(size)) 66 iotests.qemu_img_create('-f', iotests.imgfmt, img1_path, str(size)) 67 vm.add_drive(img0_path, interface='none') 68 vm.add_device('scsi-hd,id=device0,drive=drive0,bus=scsi0.0') 69 vm.add_drive(img1_path, interface='none') 70 vm.add_device('scsi-hd,id=device1,drive=drive1,bus=scsi1.0') 71 72 log('--- Starting VM ---\n') 73 vm.launch() 74 75 log('--- Create Targets & Full Backups ---\n') 76 create_target(img0_full_path, 'img0-full', size) 77 create_target(img1_full_path, 'img1-full', size) 78 ret = vm.qmp_log('transaction', indent=2, actions=[ 79 { 'type': 'block-dirty-bitmap-add', 80 'data': { 'node': 'drive0', 'name': 'bitmap0' }}, 81 { 'type': 'block-dirty-bitmap-add', 82 'data': { 'node': 'drive1', 'name': 'bitmap1' }}, 83 { 'type': 'blockdev-backup', 84 'data': { 'device': 'drive0', 85 'target': 'img0-full', 86 'sync': 'full', 87 'job-id': 'j0' }}, 88 { 'type': 'blockdev-backup', 89 'data': { 'device': 'drive1', 90 'target': 'img1-full', 91 'sync': 'full', 92 'job-id': 'j1' }} 93 ]) 94 if "error" in ret: 95 raise Exception(ret['error']['desc']) 96 vm.run_job('j0', auto_dismiss=True) 97 vm.run_job('j1', auto_dismiss=True) 98 99 log('\n--- Create Targets & Incremental Backups ---\n') 100 create_target(img0_incr_path, 'img0-incr', size) 101 create_target(img1_incr_path, 'img1-incr', size) 102 ret = vm.qmp_log('transaction', indent=2, actions=[ 103 { 'type': 'blockdev-backup', 104 'data': { 'device': 'drive0', 105 'target': 'img0-incr', 106 'sync': 'incremental', 107 'bitmap': 'bitmap0', 108 'job-id': 'j2' }}, 109 { 'type': 'blockdev-backup', 110 'data': { 'device': 'drive1', 111 'target': 'img1-incr', 112 'sync': 'incremental', 113 'bitmap': 'bitmap1', 114 'job-id': 'j3' }} 115 ]) 116 if "error" in ret: 117 raise Exception(ret['error']['desc']) 118 vm.run_job('j2', auto_dismiss=True) 119 vm.run_job('j3', auto_dismiss=True) 120 121 log('\n--- Done ---') 122 vm.shutdown() 123