xref: /openbmc/qemu/tests/qemu-iotests/057 (revision fef80ea073c4862bc9eaddb6ddb0ed970b8ad7c4)
1903cb1bfSPhilippe Mathieu-Daudé#!/usr/bin/env python3
2*9dd003a9SVladimir Sementsov-Ogievskiy# group: rw
38023090bSWenchao Xia#
48023090bSWenchao Xia# Tests for internal snapshot.
58023090bSWenchao Xia#
68023090bSWenchao Xia# Copyright (C) 2013 IBM, Inc.
78023090bSWenchao Xia#
88023090bSWenchao Xia# Based on 055.
98023090bSWenchao Xia#
108023090bSWenchao Xia# This program is free software; you can redistribute it and/or modify
118023090bSWenchao Xia# it under the terms of the GNU General Public License as published by
128023090bSWenchao Xia# the Free Software Foundation; either version 2 of the License, or
138023090bSWenchao Xia# (at your option) any later version.
148023090bSWenchao Xia#
158023090bSWenchao Xia# This program is distributed in the hope that it will be useful,
168023090bSWenchao Xia# but WITHOUT ANY WARRANTY; without even the implied warranty of
178023090bSWenchao Xia# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
188023090bSWenchao Xia# GNU General Public License for more details.
198023090bSWenchao Xia#
208023090bSWenchao Xia# You should have received a copy of the GNU General Public License
218023090bSWenchao Xia# along with this program.  If not, see <http://www.gnu.org/licenses/>.
228023090bSWenchao Xia#
238023090bSWenchao Xia
248023090bSWenchao Xiaimport time
258023090bSWenchao Xiaimport os
268023090bSWenchao Xiaimport iotests
278023090bSWenchao Xiafrom iotests import qemu_img, qemu_io
288023090bSWenchao Xia
298023090bSWenchao Xiatest_drv_base_name = 'drive'
308023090bSWenchao Xia
318023090bSWenchao Xiaclass ImageSnapshotTestCase(iotests.QMPTestCase):
328023090bSWenchao Xia    image_len = 120 * 1024 * 1024 # MB
338023090bSWenchao Xia
348023090bSWenchao Xia    def __init__(self, *args):
358023090bSWenchao Xia        self.expect = []
368023090bSWenchao Xia        super(ImageSnapshotTestCase, self).__init__(*args)
378023090bSWenchao Xia
388023090bSWenchao Xia    def _setUp(self, test_img_base_name, image_num):
398023090bSWenchao Xia        self.vm = iotests.VM()
408023090bSWenchao Xia        for i in range(0, image_num):
418023090bSWenchao Xia            filename = '%s%d' % (test_img_base_name, i)
428023090bSWenchao Xia            img = os.path.join(iotests.test_dir, filename)
438023090bSWenchao Xia            device = '%s%d' % (test_drv_base_name, i)
448023090bSWenchao Xia            qemu_img('create', '-f', iotests.imgfmt, img, str(self.image_len))
458023090bSWenchao Xia            self.vm.add_drive(img)
468023090bSWenchao Xia            self.expect.append({'image': img, 'device': device,
478023090bSWenchao Xia                                'snapshots': [],
488023090bSWenchao Xia                                'snapshots_name_counter': 0})
498023090bSWenchao Xia        self.vm.launch()
508023090bSWenchao Xia
518023090bSWenchao Xia    def tearDown(self):
528023090bSWenchao Xia        self.vm.shutdown()
538023090bSWenchao Xia        for dev_expect in self.expect:
548023090bSWenchao Xia            os.remove(dev_expect['image'])
558023090bSWenchao Xia
568023090bSWenchao Xia    def createSnapshotInTransaction(self, snapshot_num, abort = False):
578023090bSWenchao Xia        actions = []
588023090bSWenchao Xia        for dev_expect in self.expect:
598023090bSWenchao Xia            num = dev_expect['snapshots_name_counter']
608023090bSWenchao Xia            for j in range(0, snapshot_num):
618023090bSWenchao Xia                name = '%s_sn%d' % (dev_expect['device'], num)
628023090bSWenchao Xia                num = num + 1
638023090bSWenchao Xia                if abort == False:
648023090bSWenchao Xia                    dev_expect['snapshots'].append({'name': name})
658023090bSWenchao Xia                    dev_expect['snapshots_name_counter'] = num
668023090bSWenchao Xia                actions.append({
678023090bSWenchao Xia                    'type': 'blockdev-snapshot-internal-sync',
688023090bSWenchao Xia                    'data': { 'device': dev_expect['device'],
698023090bSWenchao Xia                              'name': name },
708023090bSWenchao Xia                })
718023090bSWenchao Xia
728023090bSWenchao Xia        if abort == True:
738023090bSWenchao Xia            actions.append({
748023090bSWenchao Xia                'type': 'abort',
758023090bSWenchao Xia                'data': {},
768023090bSWenchao Xia            })
778023090bSWenchao Xia
788023090bSWenchao Xia        result = self.vm.qmp('transaction', actions = actions)
798023090bSWenchao Xia
808023090bSWenchao Xia        if abort == True:
818023090bSWenchao Xia            self.assert_qmp(result, 'error/class', 'GenericError')
828023090bSWenchao Xia        else:
838023090bSWenchao Xia            self.assert_qmp(result, 'return', {})
848023090bSWenchao Xia
858023090bSWenchao Xia    def verifySnapshotInfo(self):
868023090bSWenchao Xia        result = self.vm.qmp('query-block')
878023090bSWenchao Xia
888023090bSWenchao Xia        # Verify each expected result
898023090bSWenchao Xia        for dev_expect in self.expect:
908023090bSWenchao Xia            # 1. Find the returned image value and snapshot info
918023090bSWenchao Xia            image_result = None
928023090bSWenchao Xia            for device in result['return']:
938023090bSWenchao Xia                if device['device'] == dev_expect['device']:
948023090bSWenchao Xia                    image_result = device['inserted']['image']
958023090bSWenchao Xia                    break
968023090bSWenchao Xia            self.assertTrue(image_result != None)
978023090bSWenchao Xia            # Do not consider zero snapshot case now
988023090bSWenchao Xia            sn_list_result = image_result['snapshots']
998023090bSWenchao Xia            sn_list_expect = dev_expect['snapshots']
1008023090bSWenchao Xia
1018023090bSWenchao Xia            # 2. Verify it with expect
1028023090bSWenchao Xia            self.assertTrue(len(sn_list_result) == len(sn_list_expect))
1038023090bSWenchao Xia
1048023090bSWenchao Xia            for sn_expect in sn_list_expect:
1058023090bSWenchao Xia                sn_result = None
1068023090bSWenchao Xia                for sn in sn_list_result:
1078023090bSWenchao Xia                    if sn_expect['name'] == sn['name']:
1088023090bSWenchao Xia                        sn_result = sn
1098023090bSWenchao Xia                        break
1108023090bSWenchao Xia                self.assertTrue(sn_result != None)
1118023090bSWenchao Xia                # Fill in the detail info
1128023090bSWenchao Xia                sn_expect.update(sn_result)
1138023090bSWenchao Xia
1148023090bSWenchao Xia    def deleteSnapshot(self, device, id = None, name = None):
1158023090bSWenchao Xia        sn_list_expect = None
1168023090bSWenchao Xia        sn_expect = None
1178023090bSWenchao Xia
1188023090bSWenchao Xia        self.assertTrue(id != None or name != None)
1198023090bSWenchao Xia
1208023090bSWenchao Xia        # Fill in the detail info include ID
1218023090bSWenchao Xia        self.verifySnapshotInfo()
1228023090bSWenchao Xia
1238023090bSWenchao Xia        #find the expected snapshot list
1248023090bSWenchao Xia        for dev_expect in self.expect:
1258023090bSWenchao Xia            if dev_expect['device'] == device:
1268023090bSWenchao Xia                sn_list_expect = dev_expect['snapshots']
1278023090bSWenchao Xia                break
1288023090bSWenchao Xia        self.assertTrue(sn_list_expect != None)
1298023090bSWenchao Xia
1308023090bSWenchao Xia        if id != None and name != None:
1318023090bSWenchao Xia            for sn in sn_list_expect:
1328023090bSWenchao Xia                if sn['id'] == id and sn['name'] == name:
1338023090bSWenchao Xia                    sn_expect = sn
1348023090bSWenchao Xia                    result = \
1358023090bSWenchao Xia                          self.vm.qmp('blockdev-snapshot-delete-internal-sync',
1368023090bSWenchao Xia                                      device = device,
1378023090bSWenchao Xia                                      id = id,
1388023090bSWenchao Xia                                      name = name)
1398023090bSWenchao Xia                    break
1408023090bSWenchao Xia        elif id != None:
1418023090bSWenchao Xia            for sn in sn_list_expect:
1428023090bSWenchao Xia                if sn['id'] == id:
1438023090bSWenchao Xia                    sn_expect = sn
1448023090bSWenchao Xia                    result = \
1458023090bSWenchao Xia                          self.vm.qmp('blockdev-snapshot-delete-internal-sync',
1468023090bSWenchao Xia                                      device = device,
1478023090bSWenchao Xia                                      id = id)
1488023090bSWenchao Xia                    break
1498023090bSWenchao Xia        else:
1508023090bSWenchao Xia            for sn in sn_list_expect:
1518023090bSWenchao Xia                if sn['name'] == name:
1528023090bSWenchao Xia                    sn_expect = sn
1538023090bSWenchao Xia                    result = \
1548023090bSWenchao Xia                          self.vm.qmp('blockdev-snapshot-delete-internal-sync',
1558023090bSWenchao Xia                                      device = device,
1568023090bSWenchao Xia                                      name = name)
1578023090bSWenchao Xia                    break
1588023090bSWenchao Xia
1598023090bSWenchao Xia        self.assertTrue(sn_expect != None)
1608023090bSWenchao Xia
1618023090bSWenchao Xia        self.assert_qmp(result, 'return', sn_expect)
1628023090bSWenchao Xia        sn_list_expect.remove(sn_expect)
1638023090bSWenchao Xia
1648023090bSWenchao Xiaclass TestSingleTransaction(ImageSnapshotTestCase):
1658023090bSWenchao Xia    def setUp(self):
1668023090bSWenchao Xia        self._setUp('test_a.img', 1)
1678023090bSWenchao Xia
1688023090bSWenchao Xia    def test_create(self):
1698023090bSWenchao Xia        self.createSnapshotInTransaction(1)
1708023090bSWenchao Xia        self.verifySnapshotInfo()
1718023090bSWenchao Xia
1728023090bSWenchao Xia    def test_error_name_empty(self):
1738023090bSWenchao Xia        actions = [{'type': 'blockdev-snapshot-internal-sync',
1748023090bSWenchao Xia                    'data': { 'device': self.expect[0]['device'],
1758023090bSWenchao Xia                              'name': '' },
1768023090bSWenchao Xia                  }]
1778023090bSWenchao Xia        result = self.vm.qmp('transaction', actions = actions)
1788023090bSWenchao Xia        self.assert_qmp(result, 'error/class', 'GenericError')
1798023090bSWenchao Xia
1808023090bSWenchao Xia    def test_error_device(self):
1818023090bSWenchao Xia        actions = [{'type': 'blockdev-snapshot-internal-sync',
1828023090bSWenchao Xia                    'data': { 'device': 'drive_error',
1838023090bSWenchao Xia                              'name': 'a' },
1848023090bSWenchao Xia                  }]
1858023090bSWenchao Xia        result = self.vm.qmp('transaction', actions = actions)
18675dfd402SKevin Wolf        self.assert_qmp(result, 'error/class', 'GenericError')
1878023090bSWenchao Xia
1888023090bSWenchao Xia    def test_error_exist(self):
1898023090bSWenchao Xia        self.createSnapshotInTransaction(1)
1908023090bSWenchao Xia        self.verifySnapshotInfo()
1918023090bSWenchao Xia        actions = [{'type': 'blockdev-snapshot-internal-sync',
1928023090bSWenchao Xia                    'data': { 'device': self.expect[0]['device'],
1938023090bSWenchao Xia                              'name': self.expect[0]['snapshots'][0] },
1948023090bSWenchao Xia                  }]
1958023090bSWenchao Xia        result = self.vm.qmp('transaction', actions = actions)
1968023090bSWenchao Xia        self.assert_qmp(result, 'error/class', 'GenericError')
1978023090bSWenchao Xia
1988023090bSWenchao Xiaclass TestMultipleTransaction(ImageSnapshotTestCase):
1998023090bSWenchao Xia    def setUp(self):
2008023090bSWenchao Xia        self._setUp('test_b.img', 2)
2018023090bSWenchao Xia
2028023090bSWenchao Xia    def test_create(self):
2038023090bSWenchao Xia        self.createSnapshotInTransaction(3)
2048023090bSWenchao Xia        self.verifySnapshotInfo()
2058023090bSWenchao Xia
2068023090bSWenchao Xia    def test_abort(self):
2078023090bSWenchao Xia        self.createSnapshotInTransaction(2)
2088023090bSWenchao Xia        self.verifySnapshotInfo()
2098023090bSWenchao Xia        self.createSnapshotInTransaction(3, abort = True)
2108023090bSWenchao Xia        self.verifySnapshotInfo()
2118023090bSWenchao Xia
2128023090bSWenchao Xiaclass TestSnapshotDelete(ImageSnapshotTestCase):
2138023090bSWenchao Xia    def setUp(self):
2148023090bSWenchao Xia        self._setUp('test_c.img', 1)
2158023090bSWenchao Xia
2168023090bSWenchao Xia    def test_delete_with_id(self):
2178023090bSWenchao Xia        self.createSnapshotInTransaction(2)
2188023090bSWenchao Xia        self.verifySnapshotInfo()
2198023090bSWenchao Xia        self.deleteSnapshot(self.expect[0]['device'],
2208023090bSWenchao Xia                            id = self.expect[0]['snapshots'][0]['id'])
2218023090bSWenchao Xia        self.verifySnapshotInfo()
2228023090bSWenchao Xia
2238023090bSWenchao Xia    def test_delete_with_name(self):
2248023090bSWenchao Xia        self.createSnapshotInTransaction(3)
2258023090bSWenchao Xia        self.verifySnapshotInfo()
2268023090bSWenchao Xia        self.deleteSnapshot(self.expect[0]['device'],
2278023090bSWenchao Xia                            name = self.expect[0]['snapshots'][1]['name'])
2288023090bSWenchao Xia        self.verifySnapshotInfo()
2298023090bSWenchao Xia
2308023090bSWenchao Xia    def test_delete_with_id_and_name(self):
2318023090bSWenchao Xia        self.createSnapshotInTransaction(4)
2328023090bSWenchao Xia        self.verifySnapshotInfo()
2338023090bSWenchao Xia        self.deleteSnapshot(self.expect[0]['device'],
2348023090bSWenchao Xia                            id = self.expect[0]['snapshots'][2]['id'],
2358023090bSWenchao Xia                            name = self.expect[0]['snapshots'][2]['name'])
2368023090bSWenchao Xia        self.verifySnapshotInfo()
2378023090bSWenchao Xia
2388023090bSWenchao Xia
2398023090bSWenchao Xia    def test_error_device(self):
2408023090bSWenchao Xia        result = self.vm.qmp('blockdev-snapshot-delete-internal-sync',
2418023090bSWenchao Xia                              device = 'drive_error',
2428023090bSWenchao Xia                              id = '0')
2432dfb4c03SKevin Wolf        self.assert_qmp(result, 'error/class', 'GenericError')
2448023090bSWenchao Xia
2458023090bSWenchao Xia    def test_error_no_id_and_name(self):
2468023090bSWenchao Xia        result = self.vm.qmp('blockdev-snapshot-delete-internal-sync',
2478023090bSWenchao Xia                              device = self.expect[0]['device'])
2488023090bSWenchao Xia        self.assert_qmp(result, 'error/class', 'GenericError')
2498023090bSWenchao Xia
2508023090bSWenchao Xia    def test_error_snapshot_not_exist(self):
2518023090bSWenchao Xia        self.createSnapshotInTransaction(2)
2528023090bSWenchao Xia        self.verifySnapshotInfo()
2538023090bSWenchao Xia        result = self.vm.qmp('blockdev-snapshot-delete-internal-sync',
2548023090bSWenchao Xia                              device = self.expect[0]['device'],
2558023090bSWenchao Xia                              id = self.expect[0]['snapshots'][0]['id'],
2568023090bSWenchao Xia                              name = self.expect[0]['snapshots'][1]['name'])
2578023090bSWenchao Xia        self.assert_qmp(result, 'error/class', 'GenericError')
2588023090bSWenchao Xia
2598023090bSWenchao Xiaif __name__ == '__main__':
260103cbc77SMax Reitz    iotests.main(supported_fmts=['qcow2'],
261103cbc77SMax Reitz                 supported_protocols=['file'])
262