# -*- coding: utf-8 -*-
import yaml

import utils.common.log as logger
from utils.business.param_util import ParamUtil as ParamService
from plugins.DistributedStorage.common.RestClient import StorageSSHClient
from plugins.DistributedStorage.common.base import TestCase
from utils.business.dmk_util import DmkApi
from utils.business.dmk_util import DMK_ROLE
from utils.business.account_manage_util import AccountType
from utils.business.service_monitor.service_monitor import Host
from utils.business.service_monitor.service_monitor import AuthProvider
from utils.business.service_monitor.service_monitor import deploy_agent
from utils.common.exception import HCCIException

DM_LOGIN_USER = 'admin'
FSM_USER = 'fsadmin'
CREATE_DMK_USER = 'fsadmin'
CREATE_DMK_GROUP = 'Distributed-storage'


class InstallICAgent(TestCase):
    def __init__(self, project_id, pod_id, fs_args,
                 condition=None, metadata=None, **kwargs):
        super(InstallICAgent, self).__init__(project_id, pod_id)
        self.fs_args = fs_args
        self.dmk_opr = DmkApi()
        self.pod_id = pod_id
        self.project_id = project_id
        self.param_service = ParamService()
        self.dmk_params_dict = self.dmk_opr.get_dmk_info(self.project_id)
        self.dmk_ip = self.dmk_params_dict.get('DMK_dmk_floatIp')
        self.dmk_sys_user = self.dmk_params_dict.get('DMK_dmk_ui_username')
        self.dmk_sys_pwd = self.dmk_params_dict.get('DMK_dmk_ui_password')
        self.dmk_init_pwd = self.fs_args.get('dmk_init_pwd')
        self.dmk_update_pwd = self.fs_args.get('dmk_pwd')
        self.component_name = self.fs_args.get('component_name')
        self.sub_component_name = self.fs_args.get('sub_component_name')
        self.dmk_creat_user = CREATE_DMK_USER
        self.dmk_creat_group = CREATE_DMK_GROUP
        self.dmk_role = DMK_ROLE.GROUP_MANAGER
        self.auth_provider = AuthProvider(self.dmk_ip, "8443",
                                          self.dmk_creat_user, self.dmk_update_pwd)
        self.team_id, self.account_id_root, self.account_id_general = '', '', ''

    def procedure(self):
        logger.info('Start to create dmk account.')
        self.create_dmk_user()
        logger.info('Creating a account Identity')
        self.dmk_opr.login_dmk(self.dmk_ip, self.dmk_creat_user, self.dmk_update_pwd)
        fsm_list = self.fs_args.get("fsm_list")
        logger.info('Start to create VM password identity')
        master_ip = self.fs_args.get('master_ip')
        # 获取om server ip，用于配置fsm节点域名和防火墙策略
        dns_list = self.query_dns_ip_info()
        for ip in fsm_list:
            # 避免主备节点os密码不一致，分别处理主备节点
            tag = 'master_{}' if ip == master_ip else 'slaver_{}'
            user_name = self.fs_args.get(tag.format("username"))
            pwd = self.fs_args.get(tag.format("password"))
            root_pwd = self.fs_args.get(tag.format("root_pwd"))
            try:
                id_general = self.dmk_opr.get_dmk_account_id(self.dmk_creat_user, user_name)
                self.dmk_opr.delete_dmk_account(id_general)
            except Exception as e:
                logger.info("Current common user unregistered to dmk, Detail: %s" % e)
            try:
                id_root = self.dmk_opr.get_dmk_account_id(self.dmk_creat_user, 'root')
                self.dmk_opr.delete_dmk_account(id_root)
            except Exception as e:
                logger.info("Current root user unregistered to dmk, Detail: %s" % e)
            logger.info('Start to create FSM[%s] password identity' % ip)
            self.add_ssh_account(user_name, pwd, root_pwd)
            self.deploy_ic_agent([ip], user_name)
            logger.info('The ICAgent is successfully deployed on FSM node: [{}]'.format(ip))
            # 删除FSM节点用户标识
            logger.info('Delete dmk account by root id')
            self.dmk_opr.delete_dmk_account(self.account_id_root)
            logger.info('Delete dmk account by general id')
            self.dmk_opr.delete_dmk_account(self.account_id_general)
            logger.info('Delete {} account successfully'.format(user_name))
            logger.info('Start config dns ip and add port:26401 to iptables')
            ssh_client = StorageSSHClient(ip, user_name, pwd, root_pwd)
            ssh_client.switch_root()
            logger.info("Config dns on node:{}".format(ip))
            self.config_dns_ip(ssh_client, dns_list)
            logger.info('Config dns successfully')
            logger.info('Start add port:26401 to iptables: {}'.format(ip))
            self.add_port_to_iptables_for_mo(ssh_client, ip)
            self.mo_verify_pwd_config(ssh_client, user_name)
        logger.info('ICAgent deployed successfully')

    def add_ssh_account(self, account, account_pwd, account_sudo_pwd):
        """
        账号增加统一密码标识，格式：region-id,部件名,子部件名,帐户名,帐户类型（数字）
        """
        region_id = self.fs_args.get("region_id")
        logger.info('region id:{}'.format(region_id))
        account_identity = '%s,%s,%s,%s,%s' % (region_id, self.component_name,
                                               self.sub_component_name, account, AccountType.MM_OS)
        root_account_identity = '%s,%s,%s,root,%s' % \
                                (region_id, self.component_name,
                                 self.sub_component_name, AccountType.HM_OS)

        logger.info('Add root Identity')
        self.account_id_root = self.dmk_opr.add_account_to_dmk(
            'root', self.team_id, account_sudo_pwd, account_sudo_pwd,
            account_identity=root_account_identity,
            sudo_account_identity=root_account_identity)

        logger.info('Add {} Identity'.format(account))
        self.account_id_general = self.dmk_opr.add_account_to_dmk(
            account, self.team_id, account_pwd, account_sudo_pwd,
            account_identity=account_identity,
            sudo_account_identity=root_account_identity)
        if self.account_id_general and self.account_id_root:
            logger.info("add account {} to dmk success,the account id is : {}"
                        .format(account, self.account_id_general))
        else:
            err_msg = "add account {} to dmk failed".format(account)
            raise HCCIException(621015, err_msg)

    def create_dmk_user(self):
        """
        注册DMK账号
        """
        # 创建DMK新的用户
        self.dmk_opr.login_dmk(self.dmk_ip, self.dmk_sys_user, self.dmk_sys_pwd)
        self.team_id, user_id = self.dmk_opr.create_dmk_user(
            self.dmk_creat_user, self.dmk_init_pwd, self.dmk_role, self.dmk_creat_group)
        if not self.team_id or not user_id:
            err_msg = "failed to create installation account"
            raise HCCIException(621015, err_msg)

        # 更新用户属组
        logger.info('Update user team')
        res = self.dmk_opr.update_user_to_multi_team(
            user_id, self.dmk_role, ['OTD', self.dmk_creat_group])
        if not res:
            err_msg = 'failed to update user OTD'
            raise HCCIException(621015, err_msg)

        # 更新账号密码
        logger.info('Update user passwd')
        self.dmk_opr.login_dmk(self.dmk_ip, self.dmk_creat_user, self.dmk_init_pwd)
        res = self.dmk_opr.change_dmk_user_passwd(user_id, self.dmk_init_pwd, self.dmk_update_pwd)
        if not res:
            err_msg = "change dmk user: %s password failed" % user_id
            raise HCCIException(621015, err_msg)
        logger.info("change user %s password success" % user_id)

    def deploy_ic_agent(self, ip_list, remote_user):
        """
        调用标准接口部署ICAgent
        """
        logger.info('Deployment ICAgent list: {}'.format(ip_list))
        hosts = [Host(ip, 22, ip, ip) for ip in ip_list]
        return deploy_agent(self.project_id, self.auth_provider, hosts, remote_user, 'su')

    @staticmethod
    def config_dns_ip(ssh_client, ip):
        cmd_list = [f"echo -e 'nameserver {ip[0]}\nnameserver {ip[1]}'"
                    f">> /etc/resolv.conf", 'echo last_result=$?']
        cmd = ';'.join(cmd_list)
        cmd_result = ssh_client.send_cmd_return(cmd)
        cmd_result = str(cmd_result)
        if cmd_result.find('last_result=0') == -1:
            err_msg = "Config dns ip failed: [cmd:{}, result:{}".format(cmd, cmd_result)
            raise HCCIException(621015, err_msg)

    @staticmethod
    def add_port_to_iptables_for_mo(ssh_client, ip_address):
        logger.info('Starting to add port:26401 to iptables')
        cmd_echo = "echo '"
        cmd_python_file = "' > /home/storage_iptables_tmp.sh"
        cmd_res = 'echo last_result=$?'
        cmd = ";".join([cmd_echo + SHELL_EXPRESSION + cmd_python_file, cmd_res])
        cmd_result = ssh_client.send_cmd_return(cmd)
        cmd_result = str(cmd_result)
        if cmd_result.find('last_result=0') == -1:
            err_msg = "Host [%s] failed to create script, Detail:%s" % (ip_address, cmd_result)
            raise HCCIException(621015, err_msg)
        cmd = ";".join(['bash /home/storage_iptables_tmp.sh', 'echo last_result=$?'])
        cmd_result = ssh_client.send_cmd_return(cmd)
        cmd_result = str(cmd_result)
        if cmd_result.find('last_result=0') == -1:
            err_msg = 'Host [%s] config iptables failed, Detail:%s' % (ip_address, cmd_result)
            raise HCCIException(621015, err_msg)
        cmd = ";".join(['rm -rf /home/storage_iptables_tmp.sh', 'echo last_result=$?'])
        cmd_result = ssh_client.send_cmd_return(cmd)
        cmd_result = str(cmd_result)
        if cmd_result.find('last_result=0') == -1:
            err_msg = "Host [%s] failed to rm script, Detail:%s" % (ip_address, cmd_result)
            raise HCCIException(621015, err_msg)

    @staticmethod
    def mo_verify_pwd_config(ssh_client, ip_addressr):
        """
        修改/etc/group配置文件，目的：保证操作  ManageOne运维面 -> 密码管理 -> 校验  能够成功。
        """
        logger.info('Modify the configuration file: /etc/group')
        cmd = "usermod -G wheel nobody;echo cmd_result=$?"
        logger.info('cmd is: {}'.format(cmd))
        cmd_result = ssh_client.send_cmd_return(cmd)
        cmd_result = str(cmd_result)
        if cmd_result.find('cmd_result=0') == -1:
            err_msg = "Host [%s] failed to modify configuration file, Detail:%s" \
                      % (ip_addressr, cmd_result)
            raise HCCIException(621015, err_msg)
        logger.info('The configuration file is modified successfully')

    def query_dns_ip_info(self):
        logger.info('query the DNS IP')
        public_config = self.dmk_opr.get_dmk_public_config(config_type="public")
        config_dict = yaml.safe_load(public_config)
        dns_ip_list = config_dict.get('g_dns').get('ip')
        if not dns_ip_list:
            err_msg = 'Failed to query the DNS IP: dns_ntp_om_ip_01 and dns_ntp_om_ip_01. ' \
                      'result: {}'.format(dns_ip_list)
            logger.error(err_msg)
            raise HCCIException(621016, err_msg)
        logger.info('DNS IP: {}'.format(dns_ip_list))
        return dns_ip_list


SHELL_EXPRESSION = r"""#!/usr/bin/bash
if [ -z "$(cat /etc/sysconfig/iptables | grep "\-A INPUT \-p tcp \-m tcp \-\-dport 26401 \-j ACCEPT")" ];then
    iptables -I INPUT -p tcp --dport 26401 -j ACCEPT >/dev/null 2>&1
fi
"""
