| 
									
										
										
										
											2020-01-30 17:32:23 +01:00
										 |  |  | #!/usr/bin/env python3 | 
					
						
							| 
									
										
										
										
											2021-01-16 16:44:19 +03:00
										 |  |  | # group: rw quick | 
					
						
							| 
									
										
										
										
											2018-01-19 16:57:19 +03:00
										 |  |  | # | 
					
						
							|  |  |  | # Tests for qmp command nbd-server-remove. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Copyright (c) 2017 Virtuozzo International GmbH | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # 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 os | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import iotests | 
					
						
							|  |  |  | import time | 
					
						
							| 
									
										
										
										
											2018-02-06 21:25:07 +03:00
										 |  |  | from iotests import qemu_img_create, qemu_io, filter_qemu_io, QemuIoInteractive | 
					
						
							| 
									
										
										
										
											2018-01-19 16:57:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-17 15:31:48 +02:00
										 |  |  | nbd_sock = os.path.join(iotests.sock_dir, 'nbd_sock') | 
					
						
							| 
									
										
										
										
											2018-01-19 16:57:19 +03:00
										 |  |  | nbd_uri = 'nbd+unix:///exp?socket=' + nbd_sock | 
					
						
							|  |  |  | disk = os.path.join(iotests.test_dir, 'disk') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestNbdServerRemove(iotests.QMPTestCase): | 
					
						
							|  |  |  |     def setUp(self): | 
					
						
							| 
									
										
										
										
											2018-02-06 21:25:07 +03:00
										 |  |  |         qemu_img_create('-f', iotests.imgfmt, disk, '1M') | 
					
						
							| 
									
										
										
										
											2018-01-19 16:57:19 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.vm = iotests.VM().add_drive(disk) | 
					
						
							|  |  |  |         self.vm.launch() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         address = { | 
					
						
							|  |  |  |             'type': 'unix', | 
					
						
							|  |  |  |             'data': { | 
					
						
							|  |  |  |                 'path': nbd_sock | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = self.vm.qmp('nbd-server-start', addr=address) | 
					
						
							|  |  |  |         self.assert_qmp(result, 'return', {}) | 
					
						
							|  |  |  |         result = self.vm.qmp('nbd-server-add', device='drive0', name='exp') | 
					
						
							|  |  |  |         self.assert_qmp(result, 'return', {}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def tearDown(self): | 
					
						
							|  |  |  |         self.vm.shutdown() | 
					
						
							|  |  |  |         os.remove(nbd_sock) | 
					
						
							|  |  |  |         os.remove(disk) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def remove_export(self, name, mode=None): | 
					
						
							|  |  |  |         if mode is None: | 
					
						
							|  |  |  |             return self.vm.qmp('nbd-server-remove', name=name) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return self.vm.qmp('nbd-server-remove', name=name, mode=mode) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assertExportNotFound(self, name): | 
					
						
							|  |  |  |         result = self.vm.qmp('nbd-server-remove', name=name) | 
					
						
							|  |  |  |         self.assert_qmp(result, 'error/desc', "Export 'exp' is not found") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assertExistingClients(self, result): | 
					
						
							|  |  |  |         self.assert_qmp(result, 'error/desc', "export 'exp' still in use") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assertReadOk(self, qemu_io_output): | 
					
						
							|  |  |  |         self.assertEqual( | 
					
						
							|  |  |  |                 filter_qemu_io(qemu_io_output).strip(), | 
					
						
							|  |  |  |                 'read 512/512 bytes at offset 0\n' + | 
					
						
							|  |  |  |                 '512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assertReadFailed(self, qemu_io_output): | 
					
						
							|  |  |  |         self.assertEqual(filter_qemu_io(qemu_io_output).strip(), | 
					
						
							|  |  |  |                          'read failed: Input/output error') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assertConnectFailed(self, qemu_io_output): | 
					
						
							|  |  |  |         self.assertEqual(filter_qemu_io(qemu_io_output).strip(), | 
					
						
							| 
									
										
										
										
											2019-04-28 17:54:44 +02:00
										 |  |  |                          "qemu-io: can't open device " + nbd_uri + | 
					
						
							| 
									
										
										
										
											2018-01-19 16:57:19 +03:00
										 |  |  |                          ": Requested export not available\n" | 
					
						
							|  |  |  |                          "server reported: export 'exp' not present") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def do_test_connect_after_remove(self, mode=None): | 
					
						
							|  |  |  |         args = ('-r', '-f', 'raw', '-c', 'read 0 512', nbd_uri) | 
					
						
							| 
									
										
										
										
											2022-04-18 17:14:59 -04:00
										 |  |  |         self.assertReadOk(qemu_io(*args).stdout) | 
					
						
							| 
									
										
										
										
											2018-01-19 16:57:19 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         result = self.remove_export('exp', mode) | 
					
						
							|  |  |  |         self.assert_qmp(result, 'return', {}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertExportNotFound('exp') | 
					
						
							| 
									
										
										
										
											2022-04-18 17:14:59 -04:00
										 |  |  |         self.assertConnectFailed(qemu_io(*args, check=False).stdout) | 
					
						
							| 
									
										
										
										
											2018-01-19 16:57:19 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_connect_after_remove_default(self): | 
					
						
							|  |  |  |         self.do_test_connect_after_remove() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_connect_after_remove_safe(self): | 
					
						
							|  |  |  |         self.do_test_connect_after_remove('safe') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_connect_after_remove_force(self): | 
					
						
							|  |  |  |         self.do_test_connect_after_remove('hard') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def do_test_remove_during_connect_safe(self, mode=None): | 
					
						
							|  |  |  |         qio = QemuIoInteractive('-r', '-f', 'raw', nbd_uri) | 
					
						
							|  |  |  |         self.assertReadOk(qio.cmd('read 0 512')) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = self.remove_export('exp', mode) | 
					
						
							|  |  |  |         self.assertExistingClients(result) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertReadOk(qio.cmd('read 0 512')) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         qio.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = self.remove_export('exp', mode) | 
					
						
							|  |  |  |         self.assert_qmp(result, 'return', {}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertExportNotFound('exp') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_remove_during_connect_default(self): | 
					
						
							|  |  |  |         self.do_test_remove_during_connect_safe() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_remove_during_connect_safe(self): | 
					
						
							|  |  |  |         self.do_test_remove_during_connect_safe('safe') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_remove_during_connect_hard(self): | 
					
						
							|  |  |  |         qio = QemuIoInteractive('-r', '-f', 'raw', nbd_uri) | 
					
						
							|  |  |  |         self.assertReadOk(qio.cmd('read 0 512')) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = self.remove_export('exp', 'hard') | 
					
						
							|  |  |  |         self.assert_qmp(result, 'return', {}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertReadFailed(qio.cmd('read 0 512')) | 
					
						
							|  |  |  |         self.assertExportNotFound('exp') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         qio.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_remove_during_connect_safe_hard(self): | 
					
						
							|  |  |  |         qio = QemuIoInteractive('-r', '-f', 'raw', nbd_uri) | 
					
						
							|  |  |  |         self.assertReadOk(qio.cmd('read 0 512')) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = self.remove_export('exp', 'safe') | 
					
						
							|  |  |  |         self.assertExistingClients(result) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertReadOk(qio.cmd('read 0 512')) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = self.remove_export('exp', 'hard') | 
					
						
							|  |  |  |         self.assert_qmp(result, 'return', {}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertExportNotFound('exp') | 
					
						
							|  |  |  |         self.assertReadFailed(qio.cmd('read 0 512')) | 
					
						
							|  |  |  |         qio.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							| 
									
										
										
										
											2019-09-02 21:33:19 +02:00
										 |  |  |     iotests.main(supported_fmts=['raw'], | 
					
						
							|  |  |  |                  supported_protocols=['nbd']) |