xref: /openbmc/qemu/tests/qemu-iotests/277 (revision a4d925f8f0634f72f1f03b23f0d172b7315e9ebf)
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