from __future__ import (
    absolute_import,
    division,
    print_function,
)

import json

from pcs.common import report_codes
from pcs.lib.commands.sbd import enable_sbd
from pcs.test.tools import fixture
from pcs.test.tools.command_env import get_env_tools
from pcs.test.tools.pcs_unittest import TestCase
from pcs.test.tools.misc import outdent

class EnableSbd(TestCase):
    def setUp(self):
        self.env_assist, self.config = get_env_tools(self)
        (self.config
            .runner.corosync.version()
            .corosync_conf.load(
                node_name_list=["node-1", "node-2"],
                auto_tie_breaker=True,
            )
            .http.add_communication(
                "check_auth",
                [
                    dict(
                        label="node-1",
                        output=json.dumps({"success": True}),
                        response_code=200,
                    ),
                    dict(
                        label="node-2",
                        was_connected=False,
                        errno=7,
                        error_msg="Failed connect to node-2:2224;"
                            " No route to host"
                        ,
                    ),
                ],
                action="remote/check_auth",
                param_list=[("check_auth_only", 1)],
            )
        )

    def test_fail_when_any_node_is_offline(self):
        self.env_assist.assert_raise_library_error(
            lambda: enable_sbd(
                self.env_assist.get_env(),
                default_watchdog=None,
                watchdog_dict={},
                sbd_options={},
            ),
            [],
        )
        self.env_assist.assert_reports([
            fixture.error(
                report_codes.NODE_COMMUNICATION_ERROR_UNABLE_TO_CONNECT,
                node="node-2",
                reason="Failed connect to node-2:2224; No route to host",
                command="remote/check_auth",
                force_code=report_codes.SKIP_OFFLINE_NODES,
            )
        ])

    def test_success_enable(self):
        (self.config
            .http.add_communication(
                "check_sbd",
                [
                    dict(label="node-1"),
                ],
                output=json.dumps({
                    "sbd":{
                        "installed": True,
                        "enabled": False,
                        "running": False
                    },
                    "watchdog":{
                        "path": "/dev/watchdog",
                        "exist": True,
                    }
                }),
                response_code=200,
                action="remote/check_sbd",
                param_list=[
                    ("watchdog", "/dev/watchdog"),
                    ("device_list", [])
                ],
            )
            .corosync_conf.load(
                node_name_list=["node-1", "node-2"],
                auto_tie_breaker=True,
                name="corosync_conf.load-extra",
            )
            .http.add_communication(
                "set_sbd_config",
                [
                    dict(label="node-1"),
                ],
                output=json.dumps({
                    "sbd":{
                        "installed": True,
                        "enabled": False,
                        "running": False
                    },
                    "watchdog":{
                        "path": "/dev/watchdog",
                        "exist": True,
                    }
                }),
                response_code=200,
                action="remote/set_sbd_config",
                param_list=[("config", outdent(
                    """\
                    # This file has been generated by pcs.
                    SBD_DELAY_START=no
                    SBD_OPTS="-n node-1"
                    SBD_PACEMAKER=yes
                    SBD_STARTMODE=always
                    SBD_WATCHDOG_DEV=/dev/watchdog
                    SBD_WATCHDOG_TIMEOUT=5
                    """
                ))],
            )
            .http.add_communication(
                "remove_stonith_watchdog_timeout",
                [
                    dict(label="node-1"),
                ],
                output="OK",
                response_code=200,
                action="remote/remove_stonith_watchdog_timeout",
            )
            .http.add_communication(
                "sbd_enable",
                [
                    dict(label="node-1"),
                ],
                output="SBD enabled",
                response_code=200,
                action="remote/sbd_enable",
            )
        )
        enable_sbd(
            self.env_assist.get_env(),
            default_watchdog=None,
            watchdog_dict={},
            sbd_options={},
            ignore_offline_nodes=True,
        )
        self.env_assist.assert_reports([
            fixture.info(report_codes.SBD_ENABLING_STARTED),
            fixture.warn(
                report_codes.CLUSTER_RESTART_REQUIRED_TO_APPLY_CHANGES
            ),
            fixture.warn(report_codes.OMITTING_NODE, node="node-2"),
            fixture.info(report_codes.SBD_CHECK_STARTED),
            fixture.info(report_codes.SBD_CHECK_SUCCESS, node="node-1"),
            fixture.info(report_codes.SBD_CONFIG_DISTRIBUTION_STARTED),
            fixture.info(
                report_codes.SBD_CONFIG_ACCEPTED_BY_NODE,
                node="node-1"
            ),
            fixture.info(
                report_codes.SERVICE_ENABLE_SUCCESS,
                node="node-1",
                instance=None,
                service="sbd",
            ),
        ])
