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 26iotests.script_initialize() 27 28 29nbd_sock, conf_file = file_path('nbd-sock', 'nbd-fault-injector.conf') 30 31 32def make_conf_file(event): 33 """ 34 Create configuration file for the nbd-fault-injector.py 35 36 :param event: which event the server should close a connection on 37 """ 38 with open(conf_file, 'w') as conff: 39 conff.write('[inject-error]\nevent={}\nwhen=after'.format(event)) 40 41 42def start_server_NBD(event): 43 make_conf_file(event) 44 45 srv = subprocess.Popen(['nbd-fault-injector.py', '--classic-negotiation', 46 nbd_sock, conf_file], stdout=subprocess.PIPE, 47 stderr=subprocess.STDOUT, universal_newlines=True) 48 line = srv.stdout.readline() 49 if 'Listening on ' in line: 50 log('NBD server: started') 51 else: 52 log('NBD server: ' + line.rstrip()) 53 54 return srv 55 56 57def start_client_NBD(): 58 log('NBD client: QEMU-IO write') 59 args = iotests.qemu_io_args_no_fmt + \ 60 ['-c', 'write -P 0x7 0 3M', '--image-opts', 61 'driver=nbd,server.type=unix,server.path={},' 62 'reconnect-delay=7'.format(nbd_sock)] 63 clt = subprocess.Popen(args, stdout=subprocess.PIPE, 64 stderr=subprocess.STDOUT, 65 universal_newlines=True) 66 return clt 67 68 69def check_proc_NBD(proc, connector): 70 try: 71 outs, errs = proc.communicate(timeout=10) 72 73 if proc.returncode < 0: 74 log('NBD {}: EXIT SIGNAL {}\n'.format(connector, proc.returncode)) 75 log(outs) 76 else: 77 msg = outs.split('\n', 1) 78 log('NBD {}: {}'.format(connector, msg[0])) 79 80 except subprocess.TimeoutExpired: 81 proc.kill() 82 log('NBD {}: ERROR timeout expired'.format(connector)) 83 finally: 84 if connector == 'server': 85 os.remove(nbd_sock) 86 os.remove(conf_file) 87 88 89srv = start_server_NBD('data') 90clt = start_client_NBD() 91# The server should close the connection after a client write request 92check_proc_NBD(srv, 'server') 93# Start the NBD server again 94srv = start_server_NBD('reply') 95# The client should reconnect and complete the write operation 96check_proc_NBD(clt, 'client') 97# Make it sure that server terminated 98check_proc_NBD(srv, 'server') 99