Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
qemu-iotests: add 057 internal snapshot for block device test case
Create in transaction and deletion in single command will be tested. Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
- Loading branch information
Showing
3 changed files
with
265 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <http://www.gnu.org/licenses/>. | ||
# | ||
|
||
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']) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
............ | ||
---------------------------------------------------------------------- | ||
Ran 12 tests | ||
|
||
OK |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -63,6 +63,7 @@ | |
054 rw auto | ||
055 rw auto | ||
056 rw auto backing | ||
057 rw auto | ||
059 rw auto | ||
060 rw auto | ||
061 rw auto | ||
|