From patchwork Sat Jul 20 13:31:10 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wayne Xia X-Patchwork-Id: 260455 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 6E1002C00A3 for ; Sat, 20 Jul 2013 23:37:32 +1000 (EST) Received: from localhost ([::1]:37225 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V0XLm-0005Xv-9E for incoming@patchwork.ozlabs.org; Sat, 20 Jul 2013 09:37:30 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38048) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V0XI0-0008I2-TR for qemu-devel@nongnu.org; Sat, 20 Jul 2013 09:33:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1V0XHx-0002df-Qj for qemu-devel@nongnu.org; Sat, 20 Jul 2013 09:33:36 -0400 Received: from e23smtp03.au.ibm.com ([202.81.31.145]:41668) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V0XHx-0002dV-1Y for qemu-devel@nongnu.org; Sat, 20 Jul 2013 09:33:33 -0400 Received: from /spool/local by e23smtp03.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Sat, 20 Jul 2013 23:23:23 +1000 Received: from d23dlp03.au.ibm.com (202.81.31.214) by e23smtp03.au.ibm.com (202.81.31.209) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Sat, 20 Jul 2013 23:23:21 +1000 Received: from d23relay03.au.ibm.com (d23relay03.au.ibm.com [9.190.235.21]) by d23dlp03.au.ibm.com (Postfix) with ESMTP id B24FE357804E for ; Sat, 20 Jul 2013 23:33:29 +1000 (EST) Received: from d23av02.au.ibm.com (d23av02.au.ibm.com [9.190.235.138]) by d23relay03.au.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id r6KDXJQU2359664 for ; Sat, 20 Jul 2013 23:33:19 +1000 Received: from d23av02.au.ibm.com (loopback [127.0.0.1]) by d23av02.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id r6KDXTPq016461 for ; Sat, 20 Jul 2013 23:33:29 +1000 Received: from RH63Wenchao.localdomain ([9.77.178.59]) by d23av02.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id r6KDVEgf013881; Sat, 20 Jul 2013 23:33:25 +1000 From: Wenchao Xia To: qemu-devel@nongnu.org Date: Sat, 20 Jul 2013 21:31:10 +0800 Message-Id: <1374327070-11400-9-git-send-email-xiawenc@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1374327070-11400-1-git-send-email-xiawenc@linux.vnet.ibm.com> References: <1374327070-11400-1-git-send-email-xiawenc@linux.vnet.ibm.com> X-Content-Scanned: Fidelis XPS MAILER x-cbid: 13072013-6102-0000-0000-000003E38A5C X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x-2.6.x [generic] X-Received-From: 202.81.31.145 Cc: kwolf@redhat.com, phrdina@redhat.com, famz@redhat.com, Wenchao Xia , armbru@redhat.com, lcapitulino@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, dietmar@proxmox.com Subject: [Qemu-devel] [PATCH V6 8/8] qemu-iotests: add 056 internal snapshot for block device test case X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Create in transaction and deletion in single command will be tested. Signed-off-by: Wenchao Xia --- tests/qemu-iotests/056 | 259 ++++++++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/056.out | 5 + tests/qemu-iotests/group | 1 + 3 files changed, 265 insertions(+), 0 deletions(-) create mode 100755 tests/qemu-iotests/056 create mode 100644 tests/qemu-iotests/056.out diff --git a/tests/qemu-iotests/056 b/tests/qemu-iotests/056 new file mode 100755 index 0000000..9cdd582 --- /dev/null +++ b/tests/qemu-iotests/056 @@ -0,0 +1,259 @@ +#!/usr/bin/env python +# +# Tests for internal snapshot. +# +# Copyright (C) 2013 IBM, Inc. +# +# Based on 055. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import time +import os +import iotests +from iotests import qemu_img, qemu_io + +test_drv_base_name = 'drive' + +class ImageSnapshotTestCase(iotests.QMPTestCase): + image_len = 120 * 1024 * 1024 # MB + + def __init__(self, *args): + self.expect = [] + super(ImageSnapshotTestCase, self).__init__(*args) + + def _setUp(self, test_img_base_name, image_num): + self.vm = iotests.VM() + for i in range(0, image_num): + filename = '%s%d' % (test_img_base_name, i) + img = os.path.join(iotests.test_dir, filename) + device = '%s%d' % (test_drv_base_name, i) + qemu_img('create', '-f', iotests.imgfmt, img, str(self.image_len)) + self.vm.add_drive(img) + self.expect.append({'image': img, 'device': device, + 'snapshots': [], + 'snapshots_name_counter': 0}) + self.vm.launch() + + def tearDown(self): + self.vm.shutdown() + for dev_expect in self.expect: + os.remove(dev_expect['image']) + + def createSnapshotInTransaction(self, snapshot_num, abort = False): + actions = [] + for dev_expect in self.expect: + num = dev_expect['snapshots_name_counter'] + for j in range(0, snapshot_num): + name = '%s_sn%d' % (dev_expect['device'], num) + num = num + 1 + if abort == False: + dev_expect['snapshots'].append({'name': name}) + dev_expect['snapshots_name_counter'] = num + actions.append({ + 'type': 'blockdev-snapshot-internal-sync', + 'data': { 'device': dev_expect['device'], + 'name': name }, + }) + + if abort == True: + actions.append({ + 'type': 'abort', + 'data': {}, + }) + + result = self.vm.qmp('transaction', actions = actions) + + if abort == True: + self.assert_qmp(result, 'error/class', 'GenericError') + else: + self.assert_qmp(result, 'return', {}) + + def verifySnapshotInfo(self): + result = self.vm.qmp('query-block') + + # Verify each expected result + for dev_expect in self.expect: + # 1. Find the returned image value and snapshot info + image_result = None + for device in result['return']: + if device['device'] == dev_expect['device']: + image_result = device['inserted']['image'] + break + self.assertTrue(image_result != None) + # Do not consider zero snapshot case now + sn_list_result = image_result['snapshots'] + sn_list_expect = dev_expect['snapshots'] + + # 2. Verify it with expect + self.assertTrue(len(sn_list_result) == len(sn_list_expect)) + + for sn_expect in sn_list_expect: + sn_result = None + for sn in sn_list_result: + if sn_expect['name'] == sn['name']: + sn_result = sn + break + self.assertTrue(sn_result != None) + # Fill in the detail info + sn_expect.update(sn_result) + + def deleteSnapshot(self, device, id = None, name = None): + sn_list_expect = None + sn_expect = None + + self.assertTrue(id != None or name != None) + + # Fill in the detail info include ID + self.verifySnapshotInfo() + + #find the expected snapshot list + for dev_expect in self.expect: + if dev_expect['device'] == device: + sn_list_expect = dev_expect['snapshots'] + break + self.assertTrue(sn_list_expect != None) + + if id != None and name != None: + for sn in sn_list_expect: + if sn['id'] == id and sn['name'] == name: + sn_expect = sn + result = \ + self.vm.qmp('blockdev-snapshot-delete-internal-sync', + device = device, + id = id, + name = name) + break + elif id != None: + for sn in sn_list_expect: + if sn['id'] == id: + sn_expect = sn + result = \ + self.vm.qmp('blockdev-snapshot-delete-internal-sync', + device = device, + id = id) + break + else: + for sn in sn_list_expect: + if sn['name'] == name: + sn_expect = sn + result = \ + self.vm.qmp('blockdev-snapshot-delete-internal-sync', + device = device, + name = name) + break + + self.assertTrue(sn_expect != None) + + self.assert_qmp(result, 'return', sn_expect) + sn_list_expect.remove(sn_expect) + +class TestSingleTransaction(ImageSnapshotTestCase): + def setUp(self): + self._setUp('test_a.img', 1) + + def test_create(self): + self.createSnapshotInTransaction(1) + self.verifySnapshotInfo() + + def test_error_name_empty(self): + actions = [{'type': 'blockdev-snapshot-internal-sync', + 'data': { 'device': self.expect[0]['device'], + 'name': '' }, + }] + result = self.vm.qmp('transaction', actions = actions) + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_error_device(self): + actions = [{'type': 'blockdev-snapshot-internal-sync', + 'data': { 'device': 'drive_error', + 'name': 'a' }, + }] + result = self.vm.qmp('transaction', actions = actions) + self.assert_qmp(result, 'error/class', 'DeviceNotFound') + + def test_error_exist(self): + self.createSnapshotInTransaction(1) + self.verifySnapshotInfo() + actions = [{'type': 'blockdev-snapshot-internal-sync', + 'data': { 'device': self.expect[0]['device'], + 'name': self.expect[0]['snapshots'][0] }, + }] + result = self.vm.qmp('transaction', actions = actions) + self.assert_qmp(result, 'error/class', 'GenericError') + +class TestMultipleTransaction(ImageSnapshotTestCase): + def setUp(self): + self._setUp('test_b.img', 2) + + def test_create(self): + self.createSnapshotInTransaction(3) + self.verifySnapshotInfo() + + def test_abort(self): + self.createSnapshotInTransaction(2) + self.verifySnapshotInfo() + self.createSnapshotInTransaction(3, abort = True) + self.verifySnapshotInfo() + +class TestSnapshotDelete(ImageSnapshotTestCase): + def setUp(self): + self._setUp('test_c.img', 1) + + def test_delete_with_id(self): + self.createSnapshotInTransaction(2) + self.verifySnapshotInfo() + self.deleteSnapshot(self.expect[0]['device'], + id = self.expect[0]['snapshots'][0]['id']) + self.verifySnapshotInfo() + + def test_delete_with_name(self): + self.createSnapshotInTransaction(3) + self.verifySnapshotInfo() + self.deleteSnapshot(self.expect[0]['device'], + name = self.expect[0]['snapshots'][1]['name']) + self.verifySnapshotInfo() + + def test_delete_with_id_and_name(self): + self.createSnapshotInTransaction(4) + self.verifySnapshotInfo() + self.deleteSnapshot(self.expect[0]['device'], + id = self.expect[0]['snapshots'][2]['id'], + name = self.expect[0]['snapshots'][2]['name']) + self.verifySnapshotInfo() + + + def test_error_device(self): + result = self.vm.qmp('blockdev-snapshot-delete-internal-sync', + device = 'drive_error', + id = '0') + self.assert_qmp(result, 'error/class', 'DeviceNotFound') + + def test_error_no_id_and_name(self): + result = self.vm.qmp('blockdev-snapshot-delete-internal-sync', + device = self.expect[0]['device']) + self.assert_qmp(result, 'error/class', 'GenericError') + + def test_error_snapshot_not_exist(self): + self.createSnapshotInTransaction(2) + self.verifySnapshotInfo() + result = self.vm.qmp('blockdev-snapshot-delete-internal-sync', + device = self.expect[0]['device'], + id = self.expect[0]['snapshots'][0]['id'], + name = self.expect[0]['snapshots'][1]['name']) + self.assert_qmp(result, 'error/class', 'GenericError') + +if __name__ == '__main__': + iotests.main(supported_fmts=['qcow2']) diff --git a/tests/qemu-iotests/056.out b/tests/qemu-iotests/056.out new file mode 100644 index 0000000..281b69e --- /dev/null +++ b/tests/qemu-iotests/056.out @@ -0,0 +1,5 @@ +............ +---------------------------------------------------------------------- +Ran 12 tests + +OK diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index fdc6ed1..5f5009b 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -62,3 +62,4 @@ 053 rw auto 054 rw auto 055 rw auto +056 rw auto