1*2dadedceSVladimir Sementsov-Ogievskiy#!/usr/bin/env python 2*2dadedceSVladimir Sementsov-Ogievskiy# 3*2dadedceSVladimir Sementsov-Ogievskiy# Tests for qmp command nbd-server-remove. 4*2dadedceSVladimir Sementsov-Ogievskiy# 5*2dadedceSVladimir Sementsov-Ogievskiy# Copyright (c) 2017 Virtuozzo International GmbH 6*2dadedceSVladimir Sementsov-Ogievskiy# 7*2dadedceSVladimir Sementsov-Ogievskiy# This program is free software; you can redistribute it and/or modify 8*2dadedceSVladimir Sementsov-Ogievskiy# it under the terms of the GNU General Public License as published by 9*2dadedceSVladimir Sementsov-Ogievskiy# the Free Software Foundation; either version 2 of the License, or 10*2dadedceSVladimir Sementsov-Ogievskiy# (at your option) any later version. 11*2dadedceSVladimir Sementsov-Ogievskiy# 12*2dadedceSVladimir Sementsov-Ogievskiy# This program is distributed in the hope that it will be useful, 13*2dadedceSVladimir Sementsov-Ogievskiy# but WITHOUT ANY WARRANTY; without even the implied warranty of 14*2dadedceSVladimir Sementsov-Ogievskiy# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*2dadedceSVladimir Sementsov-Ogievskiy# GNU General Public License for more details. 16*2dadedceSVladimir Sementsov-Ogievskiy# 17*2dadedceSVladimir Sementsov-Ogievskiy# You should have received a copy of the GNU General Public License 18*2dadedceSVladimir Sementsov-Ogievskiy# along with this program. If not, see <http://www.gnu.org/licenses/>. 19*2dadedceSVladimir Sementsov-Ogievskiy# 20*2dadedceSVladimir Sementsov-Ogievskiy 21*2dadedceSVladimir Sementsov-Ogievskiyimport os 22*2dadedceSVladimir Sementsov-Ogievskiyimport sys 23*2dadedceSVladimir Sementsov-Ogievskiyimport iotests 24*2dadedceSVladimir Sementsov-Ogievskiyimport time 25*2dadedceSVladimir Sementsov-Ogievskiyfrom iotests import qemu_img, qemu_io, filter_qemu_io, QemuIoInteractive 26*2dadedceSVladimir Sementsov-Ogievskiy 27*2dadedceSVladimir Sementsov-Ogievskiynbd_sock = 'nbd_sock' 28*2dadedceSVladimir Sementsov-Ogievskiynbd_uri = 'nbd+unix:///exp?socket=' + nbd_sock 29*2dadedceSVladimir Sementsov-Ogievskiydisk = os.path.join(iotests.test_dir, 'disk') 30*2dadedceSVladimir Sementsov-Ogievskiy 31*2dadedceSVladimir Sementsov-Ogievskiy 32*2dadedceSVladimir Sementsov-Ogievskiyclass TestNbdServerRemove(iotests.QMPTestCase): 33*2dadedceSVladimir Sementsov-Ogievskiy def setUp(self): 34*2dadedceSVladimir Sementsov-Ogievskiy qemu_img('create', '-f', iotests.imgfmt, disk, '1M') 35*2dadedceSVladimir Sementsov-Ogievskiy 36*2dadedceSVladimir Sementsov-Ogievskiy self.vm = iotests.VM().add_drive(disk) 37*2dadedceSVladimir Sementsov-Ogievskiy self.vm.launch() 38*2dadedceSVladimir Sementsov-Ogievskiy 39*2dadedceSVladimir Sementsov-Ogievskiy address = { 40*2dadedceSVladimir Sementsov-Ogievskiy 'type': 'unix', 41*2dadedceSVladimir Sementsov-Ogievskiy 'data': { 42*2dadedceSVladimir Sementsov-Ogievskiy 'path': nbd_sock 43*2dadedceSVladimir Sementsov-Ogievskiy } 44*2dadedceSVladimir Sementsov-Ogievskiy } 45*2dadedceSVladimir Sementsov-Ogievskiy 46*2dadedceSVladimir Sementsov-Ogievskiy result = self.vm.qmp('nbd-server-start', addr=address) 47*2dadedceSVladimir Sementsov-Ogievskiy self.assert_qmp(result, 'return', {}) 48*2dadedceSVladimir Sementsov-Ogievskiy result = self.vm.qmp('nbd-server-add', device='drive0', name='exp') 49*2dadedceSVladimir Sementsov-Ogievskiy self.assert_qmp(result, 'return', {}) 50*2dadedceSVladimir Sementsov-Ogievskiy 51*2dadedceSVladimir Sementsov-Ogievskiy def tearDown(self): 52*2dadedceSVladimir Sementsov-Ogievskiy self.vm.shutdown() 53*2dadedceSVladimir Sementsov-Ogievskiy os.remove(nbd_sock) 54*2dadedceSVladimir Sementsov-Ogievskiy os.remove(disk) 55*2dadedceSVladimir Sementsov-Ogievskiy 56*2dadedceSVladimir Sementsov-Ogievskiy def remove_export(self, name, mode=None): 57*2dadedceSVladimir Sementsov-Ogievskiy if mode is None: 58*2dadedceSVladimir Sementsov-Ogievskiy return self.vm.qmp('nbd-server-remove', name=name) 59*2dadedceSVladimir Sementsov-Ogievskiy else: 60*2dadedceSVladimir Sementsov-Ogievskiy return self.vm.qmp('nbd-server-remove', name=name, mode=mode) 61*2dadedceSVladimir Sementsov-Ogievskiy 62*2dadedceSVladimir Sementsov-Ogievskiy def assertExportNotFound(self, name): 63*2dadedceSVladimir Sementsov-Ogievskiy result = self.vm.qmp('nbd-server-remove', name=name) 64*2dadedceSVladimir Sementsov-Ogievskiy self.assert_qmp(result, 'error/desc', "Export 'exp' is not found") 65*2dadedceSVladimir Sementsov-Ogievskiy 66*2dadedceSVladimir Sementsov-Ogievskiy def assertExistingClients(self, result): 67*2dadedceSVladimir Sementsov-Ogievskiy self.assert_qmp(result, 'error/desc', "export 'exp' still in use") 68*2dadedceSVladimir Sementsov-Ogievskiy 69*2dadedceSVladimir Sementsov-Ogievskiy def assertReadOk(self, qemu_io_output): 70*2dadedceSVladimir Sementsov-Ogievskiy self.assertEqual( 71*2dadedceSVladimir Sementsov-Ogievskiy filter_qemu_io(qemu_io_output).strip(), 72*2dadedceSVladimir Sementsov-Ogievskiy 'read 512/512 bytes at offset 0\n' + 73*2dadedceSVladimir Sementsov-Ogievskiy '512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)') 74*2dadedceSVladimir Sementsov-Ogievskiy 75*2dadedceSVladimir Sementsov-Ogievskiy def assertReadFailed(self, qemu_io_output): 76*2dadedceSVladimir Sementsov-Ogievskiy self.assertEqual(filter_qemu_io(qemu_io_output).strip(), 77*2dadedceSVladimir Sementsov-Ogievskiy 'read failed: Input/output error') 78*2dadedceSVladimir Sementsov-Ogievskiy 79*2dadedceSVladimir Sementsov-Ogievskiy def assertConnectFailed(self, qemu_io_output): 80*2dadedceSVladimir Sementsov-Ogievskiy self.assertEqual(filter_qemu_io(qemu_io_output).strip(), 81*2dadedceSVladimir Sementsov-Ogievskiy "can't open device " + nbd_uri + 82*2dadedceSVladimir Sementsov-Ogievskiy ": Requested export not available\n" 83*2dadedceSVladimir Sementsov-Ogievskiy "server reported: export 'exp' not present") 84*2dadedceSVladimir Sementsov-Ogievskiy 85*2dadedceSVladimir Sementsov-Ogievskiy def do_test_connect_after_remove(self, mode=None): 86*2dadedceSVladimir Sementsov-Ogievskiy args = ('-r', '-f', 'raw', '-c', 'read 0 512', nbd_uri) 87*2dadedceSVladimir Sementsov-Ogievskiy self.assertReadOk(qemu_io(*args)) 88*2dadedceSVladimir Sementsov-Ogievskiy 89*2dadedceSVladimir Sementsov-Ogievskiy result = self.remove_export('exp', mode) 90*2dadedceSVladimir Sementsov-Ogievskiy self.assert_qmp(result, 'return', {}) 91*2dadedceSVladimir Sementsov-Ogievskiy 92*2dadedceSVladimir Sementsov-Ogievskiy self.assertExportNotFound('exp') 93*2dadedceSVladimir Sementsov-Ogievskiy self.assertConnectFailed(qemu_io(*args)) 94*2dadedceSVladimir Sementsov-Ogievskiy 95*2dadedceSVladimir Sementsov-Ogievskiy def test_connect_after_remove_default(self): 96*2dadedceSVladimir Sementsov-Ogievskiy self.do_test_connect_after_remove() 97*2dadedceSVladimir Sementsov-Ogievskiy 98*2dadedceSVladimir Sementsov-Ogievskiy def test_connect_after_remove_safe(self): 99*2dadedceSVladimir Sementsov-Ogievskiy self.do_test_connect_after_remove('safe') 100*2dadedceSVladimir Sementsov-Ogievskiy 101*2dadedceSVladimir Sementsov-Ogievskiy def test_connect_after_remove_force(self): 102*2dadedceSVladimir Sementsov-Ogievskiy self.do_test_connect_after_remove('hard') 103*2dadedceSVladimir Sementsov-Ogievskiy 104*2dadedceSVladimir Sementsov-Ogievskiy def do_test_remove_during_connect_safe(self, mode=None): 105*2dadedceSVladimir Sementsov-Ogievskiy qio = QemuIoInteractive('-r', '-f', 'raw', nbd_uri) 106*2dadedceSVladimir Sementsov-Ogievskiy self.assertReadOk(qio.cmd('read 0 512')) 107*2dadedceSVladimir Sementsov-Ogievskiy 108*2dadedceSVladimir Sementsov-Ogievskiy result = self.remove_export('exp', mode) 109*2dadedceSVladimir Sementsov-Ogievskiy self.assertExistingClients(result) 110*2dadedceSVladimir Sementsov-Ogievskiy 111*2dadedceSVladimir Sementsov-Ogievskiy self.assertReadOk(qio.cmd('read 0 512')) 112*2dadedceSVladimir Sementsov-Ogievskiy 113*2dadedceSVladimir Sementsov-Ogievskiy qio.close() 114*2dadedceSVladimir Sementsov-Ogievskiy 115*2dadedceSVladimir Sementsov-Ogievskiy result = self.remove_export('exp', mode) 116*2dadedceSVladimir Sementsov-Ogievskiy self.assert_qmp(result, 'return', {}) 117*2dadedceSVladimir Sementsov-Ogievskiy 118*2dadedceSVladimir Sementsov-Ogievskiy self.assertExportNotFound('exp') 119*2dadedceSVladimir Sementsov-Ogievskiy 120*2dadedceSVladimir Sementsov-Ogievskiy def test_remove_during_connect_default(self): 121*2dadedceSVladimir Sementsov-Ogievskiy self.do_test_remove_during_connect_safe() 122*2dadedceSVladimir Sementsov-Ogievskiy 123*2dadedceSVladimir Sementsov-Ogievskiy def test_remove_during_connect_safe(self): 124*2dadedceSVladimir Sementsov-Ogievskiy self.do_test_remove_during_connect_safe('safe') 125*2dadedceSVladimir Sementsov-Ogievskiy 126*2dadedceSVladimir Sementsov-Ogievskiy def test_remove_during_connect_hard(self): 127*2dadedceSVladimir Sementsov-Ogievskiy qio = QemuIoInteractive('-r', '-f', 'raw', nbd_uri) 128*2dadedceSVladimir Sementsov-Ogievskiy self.assertReadOk(qio.cmd('read 0 512')) 129*2dadedceSVladimir Sementsov-Ogievskiy 130*2dadedceSVladimir Sementsov-Ogievskiy result = self.remove_export('exp', 'hard') 131*2dadedceSVladimir Sementsov-Ogievskiy self.assert_qmp(result, 'return', {}) 132*2dadedceSVladimir Sementsov-Ogievskiy 133*2dadedceSVladimir Sementsov-Ogievskiy self.assertReadFailed(qio.cmd('read 0 512')) 134*2dadedceSVladimir Sementsov-Ogievskiy self.assertExportNotFound('exp') 135*2dadedceSVladimir Sementsov-Ogievskiy 136*2dadedceSVladimir Sementsov-Ogievskiy qio.close() 137*2dadedceSVladimir Sementsov-Ogievskiy 138*2dadedceSVladimir Sementsov-Ogievskiy def test_remove_during_connect_safe_hard(self): 139*2dadedceSVladimir Sementsov-Ogievskiy qio = QemuIoInteractive('-r', '-f', 'raw', nbd_uri) 140*2dadedceSVladimir Sementsov-Ogievskiy self.assertReadOk(qio.cmd('read 0 512')) 141*2dadedceSVladimir Sementsov-Ogievskiy 142*2dadedceSVladimir Sementsov-Ogievskiy result = self.remove_export('exp', 'safe') 143*2dadedceSVladimir Sementsov-Ogievskiy self.assertExistingClients(result) 144*2dadedceSVladimir Sementsov-Ogievskiy 145*2dadedceSVladimir Sementsov-Ogievskiy self.assertReadOk(qio.cmd('read 0 512')) 146*2dadedceSVladimir Sementsov-Ogievskiy 147*2dadedceSVladimir Sementsov-Ogievskiy result = self.remove_export('exp', 'hard') 148*2dadedceSVladimir Sementsov-Ogievskiy self.assert_qmp(result, 'return', {}) 149*2dadedceSVladimir Sementsov-Ogievskiy 150*2dadedceSVladimir Sementsov-Ogievskiy self.assertExportNotFound('exp') 151*2dadedceSVladimir Sementsov-Ogievskiy self.assertReadFailed(qio.cmd('read 0 512')) 152*2dadedceSVladimir Sementsov-Ogievskiy qio.close() 153*2dadedceSVladimir Sementsov-Ogievskiy 154*2dadedceSVladimir Sementsov-Ogievskiy 155*2dadedceSVladimir Sementsov-Ogievskiyif __name__ == '__main__': 156*2dadedceSVladimir Sementsov-Ogievskiy iotests.main() 157