xref: /openbmc/qemu/tests/qemu-iotests/057 (revision 8023090be592514dea4975428543edd598c65fc3)
1*8023090bSWenchao Xia#!/usr/bin/env python
2*8023090bSWenchao Xia#
3*8023090bSWenchao Xia# Tests for internal snapshot.
4*8023090bSWenchao Xia#
5*8023090bSWenchao Xia# Copyright (C) 2013 IBM, Inc.
6*8023090bSWenchao Xia#
7*8023090bSWenchao Xia# Based on 055.
8*8023090bSWenchao Xia#
9*8023090bSWenchao Xia# This program is free software; you can redistribute it and/or modify
10*8023090bSWenchao Xia# it under the terms of the GNU General Public License as published by
11*8023090bSWenchao Xia# the Free Software Foundation; either version 2 of the License, or
12*8023090bSWenchao Xia# (at your option) any later version.
13*8023090bSWenchao Xia#
14*8023090bSWenchao Xia# This program is distributed in the hope that it will be useful,
15*8023090bSWenchao Xia# but WITHOUT ANY WARRANTY; without even the implied warranty of
16*8023090bSWenchao Xia# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17*8023090bSWenchao Xia# GNU General Public License for more details.
18*8023090bSWenchao Xia#
19*8023090bSWenchao Xia# You should have received a copy of the GNU General Public License
20*8023090bSWenchao Xia# along with this program.  If not, see <http://www.gnu.org/licenses/>.
21*8023090bSWenchao Xia#
22*8023090bSWenchao Xia
23*8023090bSWenchao Xiaimport time
24*8023090bSWenchao Xiaimport os
25*8023090bSWenchao Xiaimport iotests
26*8023090bSWenchao Xiafrom iotests import qemu_img, qemu_io
27*8023090bSWenchao Xia
28*8023090bSWenchao Xiatest_drv_base_name = 'drive'
29*8023090bSWenchao Xia
30*8023090bSWenchao Xiaclass ImageSnapshotTestCase(iotests.QMPTestCase):
31*8023090bSWenchao Xia    image_len = 120 * 1024 * 1024 # MB
32*8023090bSWenchao Xia
33*8023090bSWenchao Xia    def __init__(self, *args):
34*8023090bSWenchao Xia        self.expect = []
35*8023090bSWenchao Xia        super(ImageSnapshotTestCase, self).__init__(*args)
36*8023090bSWenchao Xia
37*8023090bSWenchao Xia    def _setUp(self, test_img_base_name, image_num):
38*8023090bSWenchao Xia        self.vm = iotests.VM()
39*8023090bSWenchao Xia        for i in range(0, image_num):
40*8023090bSWenchao Xia            filename = '%s%d' % (test_img_base_name, i)
41*8023090bSWenchao Xia            img = os.path.join(iotests.test_dir, filename)
42*8023090bSWenchao Xia            device = '%s%d' % (test_drv_base_name, i)
43*8023090bSWenchao Xia            qemu_img('create', '-f', iotests.imgfmt, img, str(self.image_len))
44*8023090bSWenchao Xia            self.vm.add_drive(img)
45*8023090bSWenchao Xia            self.expect.append({'image': img, 'device': device,
46*8023090bSWenchao Xia                                'snapshots': [],
47*8023090bSWenchao Xia                                'snapshots_name_counter': 0})
48*8023090bSWenchao Xia        self.vm.launch()
49*8023090bSWenchao Xia
50*8023090bSWenchao Xia    def tearDown(self):
51*8023090bSWenchao Xia        self.vm.shutdown()
52*8023090bSWenchao Xia        for dev_expect in self.expect:
53*8023090bSWenchao Xia            os.remove(dev_expect['image'])
54*8023090bSWenchao Xia
55*8023090bSWenchao Xia    def createSnapshotInTransaction(self, snapshot_num, abort = False):
56*8023090bSWenchao Xia        actions = []
57*8023090bSWenchao Xia        for dev_expect in self.expect:
58*8023090bSWenchao Xia            num = dev_expect['snapshots_name_counter']
59*8023090bSWenchao Xia            for j in range(0, snapshot_num):
60*8023090bSWenchao Xia                name = '%s_sn%d' % (dev_expect['device'], num)
61*8023090bSWenchao Xia                num = num + 1
62*8023090bSWenchao Xia                if abort == False:
63*8023090bSWenchao Xia                    dev_expect['snapshots'].append({'name': name})
64*8023090bSWenchao Xia                    dev_expect['snapshots_name_counter'] = num
65*8023090bSWenchao Xia                actions.append({
66*8023090bSWenchao Xia                    'type': 'blockdev-snapshot-internal-sync',
67*8023090bSWenchao Xia                    'data': { 'device': dev_expect['device'],
68*8023090bSWenchao Xia                              'name': name },
69*8023090bSWenchao Xia                })
70*8023090bSWenchao Xia
71*8023090bSWenchao Xia        if abort == True:
72*8023090bSWenchao Xia            actions.append({
73*8023090bSWenchao Xia                'type': 'abort',
74*8023090bSWenchao Xia                'data': {},
75*8023090bSWenchao Xia            })
76*8023090bSWenchao Xia
77*8023090bSWenchao Xia        result = self.vm.qmp('transaction', actions = actions)
78*8023090bSWenchao Xia
79*8023090bSWenchao Xia        if abort == True:
80*8023090bSWenchao Xia            self.assert_qmp(result, 'error/class', 'GenericError')
81*8023090bSWenchao Xia        else:
82*8023090bSWenchao Xia            self.assert_qmp(result, 'return', {})
83*8023090bSWenchao Xia
84*8023090bSWenchao Xia    def verifySnapshotInfo(self):
85*8023090bSWenchao Xia        result = self.vm.qmp('query-block')
86*8023090bSWenchao Xia
87*8023090bSWenchao Xia        # Verify each expected result
88*8023090bSWenchao Xia        for dev_expect in self.expect:
89*8023090bSWenchao Xia            # 1. Find the returned image value and snapshot info
90*8023090bSWenchao Xia            image_result = None
91*8023090bSWenchao Xia            for device in result['return']:
92*8023090bSWenchao Xia                if device['device'] == dev_expect['device']:
93*8023090bSWenchao Xia                    image_result = device['inserted']['image']
94*8023090bSWenchao Xia                    break
95*8023090bSWenchao Xia            self.assertTrue(image_result != None)
96*8023090bSWenchao Xia            # Do not consider zero snapshot case now
97*8023090bSWenchao Xia            sn_list_result = image_result['snapshots']
98*8023090bSWenchao Xia            sn_list_expect = dev_expect['snapshots']
99*8023090bSWenchao Xia
100*8023090bSWenchao Xia            # 2. Verify it with expect
101*8023090bSWenchao Xia            self.assertTrue(len(sn_list_result) == len(sn_list_expect))
102*8023090bSWenchao Xia
103*8023090bSWenchao Xia            for sn_expect in sn_list_expect:
104*8023090bSWenchao Xia                sn_result = None
105*8023090bSWenchao Xia                for sn in sn_list_result:
106*8023090bSWenchao Xia                    if sn_expect['name'] == sn['name']:
107*8023090bSWenchao Xia                        sn_result = sn
108*8023090bSWenchao Xia                        break
109*8023090bSWenchao Xia                self.assertTrue(sn_result != None)
110*8023090bSWenchao Xia                # Fill in the detail info
111*8023090bSWenchao Xia                sn_expect.update(sn_result)
112*8023090bSWenchao Xia
113*8023090bSWenchao Xia    def deleteSnapshot(self, device, id = None, name = None):
114*8023090bSWenchao Xia        sn_list_expect = None
115*8023090bSWenchao Xia        sn_expect = None
116*8023090bSWenchao Xia
117*8023090bSWenchao Xia        self.assertTrue(id != None or name != None)
118*8023090bSWenchao Xia
119*8023090bSWenchao Xia        # Fill in the detail info include ID
120*8023090bSWenchao Xia        self.verifySnapshotInfo()
121*8023090bSWenchao Xia
122*8023090bSWenchao Xia        #find the expected snapshot list
123*8023090bSWenchao Xia        for dev_expect in self.expect:
124*8023090bSWenchao Xia            if dev_expect['device'] == device:
125*8023090bSWenchao Xia                sn_list_expect = dev_expect['snapshots']
126*8023090bSWenchao Xia                break
127*8023090bSWenchao Xia        self.assertTrue(sn_list_expect != None)
128*8023090bSWenchao Xia
129*8023090bSWenchao Xia        if id != None and name != None:
130*8023090bSWenchao Xia            for sn in sn_list_expect:
131*8023090bSWenchao Xia                if sn['id'] == id and sn['name'] == name:
132*8023090bSWenchao Xia                    sn_expect = sn
133*8023090bSWenchao Xia                    result = \
134*8023090bSWenchao Xia                          self.vm.qmp('blockdev-snapshot-delete-internal-sync',
135*8023090bSWenchao Xia                                      device = device,
136*8023090bSWenchao Xia                                      id = id,
137*8023090bSWenchao Xia                                      name = name)
138*8023090bSWenchao Xia                    break
139*8023090bSWenchao Xia        elif id != None:
140*8023090bSWenchao Xia            for sn in sn_list_expect:
141*8023090bSWenchao Xia                if sn['id'] == id:
142*8023090bSWenchao Xia                    sn_expect = sn
143*8023090bSWenchao Xia                    result = \
144*8023090bSWenchao Xia                          self.vm.qmp('blockdev-snapshot-delete-internal-sync',
145*8023090bSWenchao Xia                                      device = device,
146*8023090bSWenchao Xia                                      id = id)
147*8023090bSWenchao Xia                    break
148*8023090bSWenchao Xia        else:
149*8023090bSWenchao Xia            for sn in sn_list_expect:
150*8023090bSWenchao Xia                if sn['name'] == name:
151*8023090bSWenchao Xia                    sn_expect = sn
152*8023090bSWenchao Xia                    result = \
153*8023090bSWenchao Xia                          self.vm.qmp('blockdev-snapshot-delete-internal-sync',
154*8023090bSWenchao Xia                                      device = device,
155*8023090bSWenchao Xia                                      name = name)
156*8023090bSWenchao Xia                    break
157*8023090bSWenchao Xia
158*8023090bSWenchao Xia        self.assertTrue(sn_expect != None)
159*8023090bSWenchao Xia
160*8023090bSWenchao Xia        self.assert_qmp(result, 'return', sn_expect)
161*8023090bSWenchao Xia        sn_list_expect.remove(sn_expect)
162*8023090bSWenchao Xia
163*8023090bSWenchao Xiaclass TestSingleTransaction(ImageSnapshotTestCase):
164*8023090bSWenchao Xia    def setUp(self):
165*8023090bSWenchao Xia        self._setUp('test_a.img', 1)
166*8023090bSWenchao Xia
167*8023090bSWenchao Xia    def test_create(self):
168*8023090bSWenchao Xia        self.createSnapshotInTransaction(1)
169*8023090bSWenchao Xia        self.verifySnapshotInfo()
170*8023090bSWenchao Xia
171*8023090bSWenchao Xia    def test_error_name_empty(self):
172*8023090bSWenchao Xia        actions = [{'type': 'blockdev-snapshot-internal-sync',
173*8023090bSWenchao Xia                    'data': { 'device': self.expect[0]['device'],
174*8023090bSWenchao Xia                              'name': '' },
175*8023090bSWenchao Xia                  }]
176*8023090bSWenchao Xia        result = self.vm.qmp('transaction', actions = actions)
177*8023090bSWenchao Xia        self.assert_qmp(result, 'error/class', 'GenericError')
178*8023090bSWenchao Xia
179*8023090bSWenchao Xia    def test_error_device(self):
180*8023090bSWenchao Xia        actions = [{'type': 'blockdev-snapshot-internal-sync',
181*8023090bSWenchao Xia                    'data': { 'device': 'drive_error',
182*8023090bSWenchao Xia                              'name': 'a' },
183*8023090bSWenchao Xia                  }]
184*8023090bSWenchao Xia        result = self.vm.qmp('transaction', actions = actions)
185*8023090bSWenchao Xia        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
186*8023090bSWenchao Xia
187*8023090bSWenchao Xia    def test_error_exist(self):
188*8023090bSWenchao Xia        self.createSnapshotInTransaction(1)
189*8023090bSWenchao Xia        self.verifySnapshotInfo()
190*8023090bSWenchao Xia        actions = [{'type': 'blockdev-snapshot-internal-sync',
191*8023090bSWenchao Xia                    'data': { 'device': self.expect[0]['device'],
192*8023090bSWenchao Xia                              'name': self.expect[0]['snapshots'][0] },
193*8023090bSWenchao Xia                  }]
194*8023090bSWenchao Xia        result = self.vm.qmp('transaction', actions = actions)
195*8023090bSWenchao Xia        self.assert_qmp(result, 'error/class', 'GenericError')
196*8023090bSWenchao Xia
197*8023090bSWenchao Xiaclass TestMultipleTransaction(ImageSnapshotTestCase):
198*8023090bSWenchao Xia    def setUp(self):
199*8023090bSWenchao Xia        self._setUp('test_b.img', 2)
200*8023090bSWenchao Xia
201*8023090bSWenchao Xia    def test_create(self):
202*8023090bSWenchao Xia        self.createSnapshotInTransaction(3)
203*8023090bSWenchao Xia        self.verifySnapshotInfo()
204*8023090bSWenchao Xia
205*8023090bSWenchao Xia    def test_abort(self):
206*8023090bSWenchao Xia        self.createSnapshotInTransaction(2)
207*8023090bSWenchao Xia        self.verifySnapshotInfo()
208*8023090bSWenchao Xia        self.createSnapshotInTransaction(3, abort = True)
209*8023090bSWenchao Xia        self.verifySnapshotInfo()
210*8023090bSWenchao Xia
211*8023090bSWenchao Xiaclass TestSnapshotDelete(ImageSnapshotTestCase):
212*8023090bSWenchao Xia    def setUp(self):
213*8023090bSWenchao Xia        self._setUp('test_c.img', 1)
214*8023090bSWenchao Xia
215*8023090bSWenchao Xia    def test_delete_with_id(self):
216*8023090bSWenchao Xia        self.createSnapshotInTransaction(2)
217*8023090bSWenchao Xia        self.verifySnapshotInfo()
218*8023090bSWenchao Xia        self.deleteSnapshot(self.expect[0]['device'],
219*8023090bSWenchao Xia                            id = self.expect[0]['snapshots'][0]['id'])
220*8023090bSWenchao Xia        self.verifySnapshotInfo()
221*8023090bSWenchao Xia
222*8023090bSWenchao Xia    def test_delete_with_name(self):
223*8023090bSWenchao Xia        self.createSnapshotInTransaction(3)
224*8023090bSWenchao Xia        self.verifySnapshotInfo()
225*8023090bSWenchao Xia        self.deleteSnapshot(self.expect[0]['device'],
226*8023090bSWenchao Xia                            name = self.expect[0]['snapshots'][1]['name'])
227*8023090bSWenchao Xia        self.verifySnapshotInfo()
228*8023090bSWenchao Xia
229*8023090bSWenchao Xia    def test_delete_with_id_and_name(self):
230*8023090bSWenchao Xia        self.createSnapshotInTransaction(4)
231*8023090bSWenchao Xia        self.verifySnapshotInfo()
232*8023090bSWenchao Xia        self.deleteSnapshot(self.expect[0]['device'],
233*8023090bSWenchao Xia                            id = self.expect[0]['snapshots'][2]['id'],
234*8023090bSWenchao Xia                            name = self.expect[0]['snapshots'][2]['name'])
235*8023090bSWenchao Xia        self.verifySnapshotInfo()
236*8023090bSWenchao Xia
237*8023090bSWenchao Xia
238*8023090bSWenchao Xia    def test_error_device(self):
239*8023090bSWenchao Xia        result = self.vm.qmp('blockdev-snapshot-delete-internal-sync',
240*8023090bSWenchao Xia                              device = 'drive_error',
241*8023090bSWenchao Xia                              id = '0')
242*8023090bSWenchao Xia        self.assert_qmp(result, 'error/class', 'DeviceNotFound')
243*8023090bSWenchao Xia
244*8023090bSWenchao Xia    def test_error_no_id_and_name(self):
245*8023090bSWenchao Xia        result = self.vm.qmp('blockdev-snapshot-delete-internal-sync',
246*8023090bSWenchao Xia                              device = self.expect[0]['device'])
247*8023090bSWenchao Xia        self.assert_qmp(result, 'error/class', 'GenericError')
248*8023090bSWenchao Xia
249*8023090bSWenchao Xia    def test_error_snapshot_not_exist(self):
250*8023090bSWenchao Xia        self.createSnapshotInTransaction(2)
251*8023090bSWenchao Xia        self.verifySnapshotInfo()
252*8023090bSWenchao Xia        result = self.vm.qmp('blockdev-snapshot-delete-internal-sync',
253*8023090bSWenchao Xia                              device = self.expect[0]['device'],
254*8023090bSWenchao Xia                              id = self.expect[0]['snapshots'][0]['id'],
255*8023090bSWenchao Xia                              name = self.expect[0]['snapshots'][1]['name'])
256*8023090bSWenchao Xia        self.assert_qmp(result, 'error/class', 'GenericError')
257*8023090bSWenchao Xia
258*8023090bSWenchao Xiaif __name__ == '__main__':
259*8023090bSWenchao Xia    iotests.main(supported_fmts=['qcow2'])
260