1*9f7264f5SJohn Snow#!/usr/bin/env python 2*9f7264f5SJohn Snow# 3*9f7264f5SJohn Snow# Tests for incremental drive-backup 4*9f7264f5SJohn Snow# 5*9f7264f5SJohn Snow# Copyright (C) 2015 John Snow for Red Hat, Inc. 6*9f7264f5SJohn Snow# 7*9f7264f5SJohn Snow# Based on 056. 8*9f7264f5SJohn Snow# 9*9f7264f5SJohn Snow# This program is free software; you can redistribute it and/or modify 10*9f7264f5SJohn Snow# it under the terms of the GNU General Public License as published by 11*9f7264f5SJohn Snow# the Free Software Foundation; either version 2 of the License, or 12*9f7264f5SJohn Snow# (at your option) any later version. 13*9f7264f5SJohn Snow# 14*9f7264f5SJohn Snow# This program is distributed in the hope that it will be useful, 15*9f7264f5SJohn Snow# but WITHOUT ANY WARRANTY; without even the implied warranty of 16*9f7264f5SJohn Snow# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17*9f7264f5SJohn Snow# GNU General Public License for more details. 18*9f7264f5SJohn Snow# 19*9f7264f5SJohn Snow# You should have received a copy of the GNU General Public License 20*9f7264f5SJohn Snow# along with this program. If not, see <http://www.gnu.org/licenses/>. 21*9f7264f5SJohn Snow# 22*9f7264f5SJohn Snow 23*9f7264f5SJohn Snowimport os 24*9f7264f5SJohn Snowimport iotests 25*9f7264f5SJohn Snow 26*9f7264f5SJohn Snow 27*9f7264f5SJohn Snowdef io_write_patterns(img, patterns): 28*9f7264f5SJohn Snow for pattern in patterns: 29*9f7264f5SJohn Snow iotests.qemu_io('-c', 'write -P%s %s %s' % pattern, img) 30*9f7264f5SJohn Snow 31*9f7264f5SJohn Snow 32*9f7264f5SJohn Snowclass TestIncrementalBackup(iotests.QMPTestCase): 33*9f7264f5SJohn Snow def setUp(self): 34*9f7264f5SJohn Snow self.bitmaps = list() 35*9f7264f5SJohn Snow self.files = list() 36*9f7264f5SJohn Snow self.drives = list() 37*9f7264f5SJohn Snow self.vm = iotests.VM() 38*9f7264f5SJohn Snow self.err_img = os.path.join(iotests.test_dir, 'err.%s' % iotests.imgfmt) 39*9f7264f5SJohn Snow 40*9f7264f5SJohn Snow # Create a base image with a distinctive patterning 41*9f7264f5SJohn Snow drive0 = self.add_node('drive0') 42*9f7264f5SJohn Snow self.img_create(drive0['file'], drive0['fmt']) 43*9f7264f5SJohn Snow self.vm.add_drive(drive0['file']) 44*9f7264f5SJohn Snow io_write_patterns(drive0['file'], (('0x41', 0, 512), 45*9f7264f5SJohn Snow ('0xd5', '1M', '32k'), 46*9f7264f5SJohn Snow ('0xdc', '32M', '124k'))) 47*9f7264f5SJohn Snow self.vm.launch() 48*9f7264f5SJohn Snow 49*9f7264f5SJohn Snow 50*9f7264f5SJohn Snow def add_node(self, node_id, fmt=iotests.imgfmt, path=None, backup=None): 51*9f7264f5SJohn Snow if path is None: 52*9f7264f5SJohn Snow path = os.path.join(iotests.test_dir, '%s.%s' % (node_id, fmt)) 53*9f7264f5SJohn Snow if backup is None: 54*9f7264f5SJohn Snow backup = os.path.join(iotests.test_dir, 55*9f7264f5SJohn Snow '%s.full.backup.%s' % (node_id, fmt)) 56*9f7264f5SJohn Snow 57*9f7264f5SJohn Snow self.drives.append({ 58*9f7264f5SJohn Snow 'id': node_id, 59*9f7264f5SJohn Snow 'file': path, 60*9f7264f5SJohn Snow 'backup': backup, 61*9f7264f5SJohn Snow 'fmt': fmt }) 62*9f7264f5SJohn Snow return self.drives[-1] 63*9f7264f5SJohn Snow 64*9f7264f5SJohn Snow 65*9f7264f5SJohn Snow def img_create(self, img, fmt=iotests.imgfmt, size='64M', 66*9f7264f5SJohn Snow parent=None, parentFormat=None): 67*9f7264f5SJohn Snow if parent: 68*9f7264f5SJohn Snow if parentFormat is None: 69*9f7264f5SJohn Snow parentFormat = fmt 70*9f7264f5SJohn Snow iotests.qemu_img('create', '-f', fmt, img, size, 71*9f7264f5SJohn Snow '-b', parent, '-F', parentFormat) 72*9f7264f5SJohn Snow else: 73*9f7264f5SJohn Snow iotests.qemu_img('create', '-f', fmt, img, size) 74*9f7264f5SJohn Snow self.files.append(img) 75*9f7264f5SJohn Snow 76*9f7264f5SJohn Snow def test_sync_dirty_bitmap_missing(self): 77*9f7264f5SJohn Snow self.assert_no_active_block_jobs() 78*9f7264f5SJohn Snow self.files.append(self.err_img) 79*9f7264f5SJohn Snow result = self.vm.qmp('drive-backup', device=self.drives[0]['id'], 80*9f7264f5SJohn Snow sync='dirty-bitmap', format=self.drives[0]['fmt'], 81*9f7264f5SJohn Snow target=self.err_img) 82*9f7264f5SJohn Snow self.assert_qmp(result, 'error/class', 'GenericError') 83*9f7264f5SJohn Snow 84*9f7264f5SJohn Snow 85*9f7264f5SJohn Snow def test_sync_dirty_bitmap_not_found(self): 86*9f7264f5SJohn Snow self.assert_no_active_block_jobs() 87*9f7264f5SJohn Snow self.files.append(self.err_img) 88*9f7264f5SJohn Snow result = self.vm.qmp('drive-backup', device=self.drives[0]['id'], 89*9f7264f5SJohn Snow sync='dirty-bitmap', bitmap='unknown', 90*9f7264f5SJohn Snow format=self.drives[0]['fmt'], target=self.err_img) 91*9f7264f5SJohn Snow self.assert_qmp(result, 'error/class', 'GenericError') 92*9f7264f5SJohn Snow 93*9f7264f5SJohn Snow 94*9f7264f5SJohn Snow def tearDown(self): 95*9f7264f5SJohn Snow self.vm.shutdown() 96*9f7264f5SJohn Snow for filename in self.files: 97*9f7264f5SJohn Snow try: 98*9f7264f5SJohn Snow os.remove(filename) 99*9f7264f5SJohn Snow except OSError: 100*9f7264f5SJohn Snow pass 101*9f7264f5SJohn Snow 102*9f7264f5SJohn Snow 103*9f7264f5SJohn Snowif __name__ == '__main__': 104*9f7264f5SJohn Snow iotests.main(supported_fmts=['qcow2']) 105