"""
persistent write log cache recovery task
"""
import contextlib
import logging
import random
import json
import time

from teuthology import misc as teuthology
from teuthology import contextutil

DEFAULT_NUM_ITERATIONS = 20
IO_PATTERNS = ("full-seq", "rand")
IO_SIZES = ('4K', '16K', '128K', '1024K')

log = logging.getLogger(__name__)

@contextlib.contextmanager
def thrashes_rbd_bench_on_persistent_cache(ctx, config):
    """
    thrashes rbd bench on persistent write log cache.
    It can test recovery feature of persistent write log cache.
    """
    log.info("thrashes rbd bench on persistent write log cache")

    client, client_config = list(config.items())[0]
    (remote,) = ctx.cluster.only(client).remotes.keys()
    client_config = client_config if client_config is not None else dict()
    image_name = client_config.get('image_name', 'testimage')
    num_iterations = client_config.get('num_iterations', DEFAULT_NUM_ITERATIONS)

    for i in range(num_iterations):
        log.info("start rbd bench")
        # rbd bench could not specify the run time so set a large enough test size.
        remote.run(
            args=[
                'rbd', 'bench',
                '--io-type', 'write',
                '--io-pattern', random.choice(IO_PATTERNS),
                '--io-size', random.choice(IO_SIZES),
                '--io-total', '100G',
                image_name,
                ],
            wait=False,
        )
        # Wait a few seconds for the rbd bench process to run
        # and complete the pwl cache initialization
        time.sleep(10)
        log.info("dump cache state when rbd bench running.")
        remote.sh(['rbd', 'status', image_name, '--format=json'])
        log.info("sleep...")
        time.sleep(random.randint(10, 60))
        log.info("rbd bench crash.")
        remote.run(
            args=[
                'killall', '-9', 'rbd',
                ],
            check_status=False,
        )
        log.info("wait for watch timeout.")
        time.sleep(40)
        log.info("check cache state after crash.")
        out = remote.sh(['rbd', 'status', image_name, '--format=json'])
        rbd_status = json.loads(out)
        assert len(rbd_status['watchers']) == 0
        assert rbd_status['persistent_cache']['present'] == True
        assert rbd_status['persistent_cache']['empty'] == False
        assert rbd_status['persistent_cache']['clean'] == False
        log.info("check dirty cache file.")
        remote.run(
            args=[
                'test', '-e', rbd_status['persistent_cache']['path'],
                ]
        )
    try:
        yield
    finally:
        log.info("cleanup")

@contextlib.contextmanager
def task(ctx, config):
    """
    This is task for testing persistent write log cache recovery.
    """
    assert isinstance(config, dict), \
            "task rbd_pwl_cache_recovery only supports a dictionary for configuration"

    managers = []
    config = teuthology.replace_all_with_clients(ctx.cluster, config)
    managers.append(
        lambda: thrashes_rbd_bench_on_persistent_cache(ctx=ctx, config=config)
        )

    with contextutil.nested(*managers):
        yield
