#!/usr/bin/env python3
# group: rw quick
#
# Test NBD client reconnection
#
# Copyright (c) 2019 Virtuozzo International GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

import os
import subprocess
import iotests
from iotests import file_path, log

iotests.script_initialize()


conf_file = file_path('nbd-fault-injector.conf')
nbd_sock = file_path('nbd-sock', base_dir=iotests.sock_dir)


def make_conf_file(event):
    """
    Create configuration file for the nbd-fault-injector.py

    :param event: which event the server should close a connection on
    """
    with open(conf_file, 'w') as conff:
        conff.write('[inject-error]\nevent={}\nwhen=after'.format(event))


def start_server_NBD(event):
    make_conf_file(event)

    srv = subprocess.Popen(['./nbd-fault-injector.py', '--classic-negotiation',
                           nbd_sock, conf_file], stdout=subprocess.PIPE,
                           stderr=subprocess.STDOUT, universal_newlines=True)
    line = srv.stdout.readline()
    if 'Listening on ' in line:
        log('NBD server: started')
    else:
        log('NBD server: ' + line.rstrip())

    return srv


def start_client_NBD():
    log('NBD client: QEMU-IO write')
    args = iotests.qemu_io_args_no_fmt + \
        ['-c', 'write -P 0x7 0 3M', '--image-opts',
         'driver=nbd,server.type=unix,server.path={},'
         'reconnect-delay=7'.format(nbd_sock)]
    clt = subprocess.Popen(args, stdout=subprocess.PIPE,
                           stderr=subprocess.STDOUT,
                           universal_newlines=True)
    return clt


def check_proc_NBD(proc, connector):
    try:
        outs, errs = proc.communicate(timeout=10)

        if proc.returncode < 0:
            log('NBD {}: EXIT SIGNAL {}\n'.format(connector, proc.returncode))
            log(outs)
        else:
            msg = outs.split('\n', 1)
            log('NBD {}: {}'.format(connector, msg[0]))

    except subprocess.TimeoutExpired:
        proc.kill()
        log('NBD {}: ERROR timeout expired'.format(connector))
    finally:
        if connector == 'server':
            os.remove(nbd_sock)
            os.remove(conf_file)


srv = start_server_NBD('data')
clt = start_client_NBD()
# The server should close the connection after a client write request
check_proc_NBD(srv, 'server')
# Start the NBD server again
srv = start_server_NBD('reply')
# The client should reconnect and complete the write operation
check_proc_NBD(clt, 'client')
# Make it sure that server terminated
check_proc_NBD(srv, 'server')
