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