# -*- coding:utf-8 -*-
import os
from utils.common.fic_base import StepBaseInterface
from utils.common.message import Message
import utils.common.log as logger
from platforms.upgradecheck.check_result import CheckResult
from utils.DBAdapter.DBConnector import BaseOps
from utils.common.ssh_util import Ssh
from plugins.eBackup.common.util import Utils, get_eBackup_Driver_nodes, get_cascaded_reverse_ips
from utils.common.exception import FCUException
from plugins.eBackup.common.ebackup_patch import EbackupPatchTool


class DatamoverPatchPrecheck(StepBaseInterface):
    def __init__(self, project_id, pod_id, regionid_list, az_id=None):
        self.project_id = project_id
        self.pod_id = pod_id
        self.regionid_list = regionid_list
        self.param_dict = Utils.init_system_params(project_id, regionid_list[0])

    def execute(self, project_id, pod_id, regionid_list, az_id=None):
        try:
            datamover_nodes = self.param_dict['eBackup_Datamover_nodes'].replace('|', ';').split(';')
            check_results = []

            patch_tool = EbackupPatchTool(datamover_nodes, self.param_dict, "datamover")
            is_true = patch_tool.precheck(check_results)
            if not is_true:
                logger.error("Prechecking is not passed.")
            else:
                logger.info("Prechecking is passed.")
            
            return Message(200, check_results=check_results)
        except Exception as ex:
            logger.error(str(ex))
            return Message(500, error_msg_cn="升级前检查出现异常，请查看日志并重试",
                           error_msg_en="Exception occurs while prechecking,please check the log and try again.")

    def retry(self, project_id, pod_id, regionid_list, az_id=None):
        return self.execute(project_id, pod_id, regionid_list)


class WorkflowPatchPrecheck(StepBaseInterface):
    def __init__(self, project_id, pod_id, regionid_list, az_id=None):
        self.project_id = project_id
        self.pod_id = pod_id
        self.regionid_list = regionid_list
        self.param_dict = Utils.init_system_params(project_id, regionid_list[0])

    def execute(self, project_id, pod_id, regionid_list, az_id=None):
        try:
            workflow_nodes = self.param_dict['eBackup_Workflow_nodes'].split(';')
            check_results = []
            patch_tool = EbackupPatchTool(workflow_nodes, self.param_dict, "workflow")
            is_true = patch_tool.precheck(check_results)
            if not is_true:
                logger.error("Prechecking is not passed.")
            else:
                logger.info("Prechecking is passed.")
            
            return Message(200, check_results=check_results)
        except Exception as ex:
            logger.error(str(ex))
            return Message(500, error_msg_cn="升级前检查出现异常，请查看日志并重试",
                           error_msg_en="Exception occurs while prechecking,please check the log and try again.")
            
    def retry(self, project_id, pod_id, regionid_list, az_id=None):
        return self.execute(project_id, pod_id, regionid_list)


class DriverPatchPrecheck(StepBaseInterface):
    def __init__(self, project_id, pod_id, regionid_list):
        super(DriverPatchPrecheck, self).__init__(project_id, pod_id, regionid_list)
        self.project_id = project_id
        self.pod_id = pod_id
        self.regionid_list = regionid_list
        self.region_id = regionid_list[0]
        self.database = BaseOps()
        self.__db_param_dict = Utils.init_system_params(project_id, regionid_list[0])
        self.__ssh = Ssh()

    def _execute_precheck(self, reverse_proxy_ip):
        try:
            version_check_cmds = '''cat /usr/lib/python2.7/site-packages/cinder/backup/drivers/ebackupversion.conf 2>/dev/null || ''' + \
            '''cat /opt/cloud/services/cascading-cinder/venv/lib/python2.7/site-packages/cinder/backup/drivers/ebackupversion.conf 2>/dev/null || ''' + \
            '''cat /usr/lib64/python2.7/site-packages/cinder/backup/drivers/ebackupversion.conf 2>/dev/null'''
            
            driver_host_dict = get_eBackup_Driver_nodes(reverse_proxy_ip, self.__db_param_dict)
            if not driver_host_dict:
                logger.info("eBackup is not supported in the cascaded layer:" + reverse_proxy_ip)
                return True, {}
            driver_ip_array = driver_host_dict["eBackupDriver"]
            login_user = "fsp"
            login_password = self.__db_param_dict['openstack_fsp_pwd']
            root_pwd = self.__db_param_dict['openstack_root_pwd']
            uninstalled_ips = []
            installed_ips = []
            for server_ip in driver_ip_array:
                ssh_client = self.__ssh.ssh_create_client(server_ip, login_user, login_password)
                self.__ssh.ssh_send_command(ssh_client, 'su - root', 'Password:', 100)
                self.__ssh.ssh_send_command(ssh_client, root_pwd, '#', 100)
                result = self.__ssh.ssh_exec_command_return_list(ssh_client, version_check_cmds)
                self.__ssh.ssh_close(ssh_client)
                logger.info("dirver node " + server_ip + " version is " + str(result))

                if -1 == str(result).find('eBackupVersion'):
                    uninstalled_ips.append(server_ip)
                else:
                    installed_ips.append(server_ip)
            file_path = os.path.abspath(__file__ + '/../' + reverse_proxy_ip + '.txt')
            if 0 != len(installed_ips):
                with open(file_path, mode='w') as fp:
                    fp.truncate()
                    # write cps node to file
                    fp.write(','.join(driver_host_dict["cpsnode"]) + '\n')
                    # write driver node to file
                    fp.write(','.join(installed_ips) + '\n')
                    if len(installed_ips) != len(driver_ip_array):
                        return False, {"uninstalled_ips": uninstalled_ips, "all_uninstalled": False}
                    else:
                        return True, {}
            else:
                if os.path.exists(file_path):
                    os.remove(file_path)
                logger.error("eBackup driver is not installed in the cascaded layer:" + reverse_proxy_ip)
                return False, {"uninstalled_ips": uninstalled_ips, "all_uninstalled": True}

        except Exception as ex:
            logger.error(str(ex))
            return False, {"Exception": str(ex)}

    def execute(self, project_id, pod_id, regionid_list):
        # in 8.0.0 it is no need to check if the eBackup driver existed at driver nodes
        # return Message(200, check_results=eBackup_Driver_status_check_SUCCESS)
        region_type = self.database.get_region_type(self.project_id)
        logger.info("The network type is %s" % region_type)
        check_result = []
        if region_type.lower() == "type1":
            try:
                cascaded_reverse_ips = get_cascaded_reverse_ips(self.__db_param_dict)
                if 0 == len(cascaded_reverse_ips):
                    logger.error("Fail to get reverse proxy ips of the cascaded layers.")
                    raise Exception("Fail to get reverse proxy ips of the cascaded layers.")
                error_msg_dict = {}
                for each_reverse_ip in cascaded_reverse_ips:
                    logger.info("Begin to precheck the cascaded layer %s" % each_reverse_ip)
                    is_true, error_msg = self._execute_precheck(each_reverse_ip)
                    if not is_true and 'Exception' in error_msg:
                        error_msg_dict.update({each_reverse_ip: error_msg['Exception']})
                        continue

                if 0 != len(error_msg_dict):
                    driver_check_result = CheckResult(itemname_ch="查询fsp集群中的eBackup Driver节点",
                                                      itemname_en="Query the eBackup Driver node in the FSP cluster",
                                                      status="failure",
                                                      error_msg_cn=FCUException(650008, str(error_msg_dict)))
                else:
                    driver_check_result = CheckResult(itemname_ch="查询fsp集群中的eBackup Driver节点",
                                                      itemname_en="Query the eBackup Driver node in the FSP cluster",
                                                      status="success")

                check_result.append(driver_check_result)

                return Message(200, check_results=check_result)
            except Exception as ex:
                logger.error(str(ex))
                return Message(500, str(ex), str(ex))
        else:
            try:
                reverse_proxy_ip = self.__db_param_dict['openstack_reverse_proxy_ip']

                check_result = []
                is_true, error_msg = self._execute_precheck(reverse_proxy_ip)

                if 'Exception' in error_msg:
                    driver_check_result = CheckResult(itemname_ch="查询fsp集群中的eBackup Driver节点",
                                                      itemname_en="Query the eBackup Driver node in the FSP cluster",
                                                      status="failure",
                                                      error_msg_cn=FCUException(650008, error_msg['Exception']))
                else:
                    driver_check_result = CheckResult(itemname_ch="查询fsp集群中的eBackup Driver节点",
                                                      itemname_en="Query the eBackup Driver node in the FSP cluster",
                                                      status="success")
                check_result.append(driver_check_result)
                return Message(200, check_results=check_result)
            except Exception as ex:
                logger.error(str(ex))
                return Message(500, str(ex), str(ex))


    def retry(self, project_id, pod_id, regionid_list):
        return self.execute(project_id, pod_id, regionid_list)