1#!/usr/bin/env python
2#
3# Copyright (C) 2017 Red Hat, Inc.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program.  If not, see <http://www.gnu.org/licenses/>.
17#
18# Creator/Owner: Stefan Hajnoczi <stefanha@redhat.com>
19#
20# Check that QMP 'migrate' with multiple drives on a single IOThread completes
21# successfully.  This particular command triggered a hang in the source QEMU
22# process due to recursive AioContext locking in bdrv_invalidate_all() and
23# BDRV_POLL_WHILE().
24
25import iotests
26
27iotests.verify_image_format(supported_fmts=['qcow2'])
28iotests.verify_platform(['linux'])
29
30with iotests.FilePath('disk0.img') as disk0_img_path, \
31     iotests.FilePath('disk1.img') as disk1_img_path, \
32     iotests.VM() as vm:
33
34    img_size = '10M'
35    iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk0_img_path, img_size)
36    iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk1_img_path, img_size)
37
38    iotests.log('Launching VM...')
39    (vm.add_object('iothread,id=iothread0')
40       .add_drive(disk0_img_path, 'node-name=drive0-node', interface='none')
41       .add_drive(disk1_img_path, 'node-name=drive1-node', interface='none')
42       .launch())
43
44    iotests.log('Setting IOThreads...')
45    iotests.log(vm.qmp('x-blockdev-set-iothread',
46                       node_name='drive0-node', iothread='iothread0',
47                       force=True))
48    iotests.log(vm.qmp('x-blockdev-set-iothread',
49                       node_name='drive1-node', iothread='iothread0',
50                       force=True))
51
52    iotests.log('Enabling migration QMP events...')
53    iotests.log(vm.qmp('migrate-set-capabilities', capabilities=[
54        {
55            'capability': 'events',
56            'state': True
57        }
58    ]))
59
60    iotests.log('Starting migration...')
61    iotests.log(vm.qmp('migrate', uri='exec:cat >/dev/null'))
62    while True:
63        event = vm.event_wait('MIGRATION')
64        iotests.log(event, filters=[iotests.filter_qmp_event])
65        if event['data']['status'] == 'completed':
66            break
67