1#!/usr/bin/env python3 2# 3# Test NBD client reconnection 4# 5# Copyright (c) 2019 Virtuozzo International GmbH 6# 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 2 of the License, or 10# (at your option) any later version. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program. If not, see <http://www.gnu.org/licenses/>. 19# 20 21import os 22import subprocess 23import iotests 24from iotests import file_path, log 25 26 27nbd_sock, conf_file = file_path('nbd-sock', 'nbd-fault-injector.conf') 28 29 30def make_conf_file(event): 31 """ 32 Create configuration file for the nbd-fault-injector.py 33 34 :param event: which event the server should close a connection on 35 """ 36 with open(conf_file, 'w') as conff: 37 conff.write('[inject-error]\nevent={}\nwhen=after'.format(event)) 38 39 40def start_server_NBD(event): 41 make_conf_file(event) 42 43 srv = subprocess.Popen(['nbd-fault-injector.py', '--classic-negotiation', 44 nbd_sock, conf_file], stdout=subprocess.PIPE, 45 stderr=subprocess.STDOUT, universal_newlines=True) 46 line = srv.stdout.readline() 47 if 'Listening on ' in line: 48 log('NBD server: started') 49 else: 50 log('NBD server: ' + line.rstrip()) 51 52 return srv 53 54 55def start_client_NBD(): 56 log('NBD client: QEMU-IO write') 57 args = iotests.qemu_io_args_no_fmt + \ 58 ['-c', 'write -P 0x7 0 3M', '--image-opts', 59 'driver=nbd,server.type=unix,server.path={},' 60 'reconnect-delay=7'.format(nbd_sock)] 61 clt = subprocess.Popen(args, stdout=subprocess.PIPE, 62 stderr=subprocess.STDOUT, 63 universal_newlines=True) 64 return clt 65 66 67def check_proc_NBD(proc, connector): 68 try: 69 outs, errs = proc.communicate(timeout=10) 70 71 if proc.returncode < 0: 72 log('NBD {}: EXIT SIGNAL {}\n'.format(connector, proc.returncode)) 73 log(outs) 74 else: 75 msg = outs.split('\n', 1) 76 log('NBD {}: {}'.format(connector, msg[0])) 77 78 except subprocess.TimeoutExpired: 79 proc.kill() 80 log('NBD {}: ERROR timeout expired'.format(connector)) 81 finally: 82 if connector == 'server': 83 os.remove(nbd_sock) 84 os.remove(conf_file) 85 86 87srv = start_server_NBD('data') 88clt = start_client_NBD() 89# The server should close the connection after a client write request 90check_proc_NBD(srv, 'server') 91# Start the NBD server again 92srv = start_server_NBD('reply') 93# The client should reconnect and complete the write operation 94check_proc_NBD(clt, 'client') 95# Make it sure that server terminated 96check_proc_NBD(srv, 'server') 97