#    Copyright 2017 Mirantis, Inc.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import pytest

from tcp_tests import logger
from tcp_tests.helpers import ext
from tcp_tests.managers import ceph_manager

LOG = logger.logger


@pytest.fixture(scope='function')
def ceph_actions(config, underlay, salt_deployed):
    """Fixture that provides various actions for OpenStack

    :param config: fixture provides oslo.config
    :param underlay: fixture provides underlay manager
    :param salt_deployed: fixture provides salt manager
    :rtype: CephManager

    For use in tests or fixtures to deploy a custom OpenStack
    """
    return ceph_manager.CephManager(config, underlay, salt_deployed)


@pytest.mark.revert_snapshot(ext.SNAPSHOT.ceph_deployed)
@pytest.fixture(scope='function')
def ceph_deployed(revert_snapshot, request, config,
                  hardware, underlay, common_services_deployed,
                  salt_deployed, ceph_actions):
    """Fixture to get or install Ceph services on environment

    :param revert_snapshot: fixture that reverts snapshot that is specified
                            in test with @pytest.mark.revert_snapshot(<name>)
    :param request: fixture provides pytest data
    :param config: fixture provides oslo.config
    :param hardware: fixture provides enviromnet manager
    :param underlay: fixture provides underlay manager
    :param common_services_deployed: fixture provides CommonServicesManager
    :param ceph_actions: fixture provides CephManager instance
    :rtype: CephManager

    If config.ceph.ceph_installed is not set, this fixture assumes
    that the ceph services were not installed, and do the following:
    - install ceph services
    - make snapshot with name 'ceph_deployed'
    - return CephManager instance

    If config.ceph.ceph_installed was set, this fixture assumes that
    the ceph services were already installed, and do the following:
    - return CephManager instance

    If you want to revert 'ceph_deployed' snapshot, please use mark:
    @pytest.mark.revert_snapshot("ceph_deployed")
    """
    # Deploy Ceph cluster
    if not config.ceph.ceph_installed:
        steps_path = config.ceph_deploy.ceph_steps_path
        commands = underlay.read_template(steps_path)
        ceph_actions.install(commands)
        hardware.create_snapshot(ext.SNAPSHOT.ceph_deployed)
        salt_deployed.sync_time()

    else:
        # 1. hardware environment created and powered on
        # 2. config.underlay.ssh contains SSH access to provisioned nodes
        #    (can be passed from external config with TESTS_CONFIGS variable)
        # 3. config.tcp.* options contain access credentials to the already
        #    installed TCP API endpoint
        pass

    return ceph_actions
