xref: /qemu/tests/qemu-iotests/277 (revision 208b2d24)
1#!/usr/bin/env python
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