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