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