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