# -*- coding: utf-8 -*-
import traceback
from utils.common.fic_base import TestCase
import utils.common.log as logger
from utils.common.message import Message
from utils.common.exception import HCCIException
from plugins.DistributedStorage.logic.DeployOperate import DeployOperate
from plugins.DistributedStorage.utils.common.DeployConstant \
    import DeployConstant


class CreateClient(TestCase):
    def __init__(self, project_id, pod_id, fs_args, condition=None,
                 metadata=None, **kwargs):
        super(CreateClient, self).__init__(project_id, pod_id)

        self.fsa_list = fs_args.get('fsa_list')
        self.opr = DeployOperate({'float_ip': fs_args.get('float_ip')})
        self.update_pwd = fs_args['dm_update_pwd']
        self.iscsi_condition = fs_args['iscsi_condition']
        self.vbs_client_list = fs_args['vbs_client_list']

        self.condition = condition
        self.metadata = metadata
        self.more_args = kwargs

    def procedure(self):
        try:
            logger.info("Start to create client.")

            self.login_dm()

            self.check_cluster()

            self.check_pool()

            logger.info("Check whether VBS is installed.")
            vbs_ip_list = [vbs.get('om_ip') for vbs in self.vbs_client_list]
            logger.info("Check whether VBS is installed.")

            self.get_vbs_ip_list(vbs_ip_list)

            self.create_client(vbs_ip_list)

            if self.iscsi_condition:
                self.config_iscsi_port()

            logger.info('Create VBS client success')
        except HCCIException as e:
            logger.error(traceback.format_exc())
            return Message(500, e)
        except Exception as e:
            logger.error(traceback.format_exc())
            return Message(500, HCCIException(626001, str(e)))
        finally:
            self.opr.logout()
        return Message()

    def get_vbs_ip_list(self, vbs_ip_list):
        rsp_obj = self.opr.query_cluster_servers()
        rsp_code, rsp_result, rsp_data = rsp_obj.get_rsp_data()
        error_code = rsp_result.get("code")
        if rsp_code != 0 or error_code != 0:
            error_des = rsp_result.get('description')
            error_sgt = rsp_result.get('suggestion')
            err_msg = "Failed to query the node to install vbs, Detail:[%s]%s.Suggestion:%s" % (
                error_code, error_des, error_sgt)
            logger.error(err_msg)
            raise Exception(err_msg)
        for server in rsp_data:
            ip = server.get('management_ip')
            if ip in vbs_ip_list and "vbs" in server.get('usage'):
                vbs_ip_list.remove(server.get('management_ip'))
                logger.info("VBS has been installed on node[%s]." % ip)

    def login_dm(self):
        """
        登陆存储
        :return:
        """
        status_code, error_code, error_des = \
            self.opr.login(DeployConstant.DM_LOGIN_USER, self.update_pwd)
        if status_code != 200 or error_code != 0:
            err_msg = "Failed to login deploy manager, Detail:" \
                      "[status:%s,code:%s]%s" % (status_code, error_code,
                                                 error_des)
            logger.error(err_msg)
            raise Exception(err_msg)

    def check_cluster(self):
        """
        检查存储集群
        :return:
        """
        logger.info('Check cluster...')
        rsp_result, rsp_data = self.opr.get_manage_cluster()
        if not rsp_data.get('clusterName'):
            logger.error('Check cluster fail...')
            raise Exception("Check cluster fail...")
        else:
            logger.error('Check cluster successfully...')

    def check_pool(self):
        """
        检查存储池
        :return:
        """
        logger.info('Check pool...')
        rsp_result, rsp_data = self.opr.get_storage_pool()
        if len(rsp_data.get('storagePools')) == 0:
            logger.error('Check pool fail...')
            raise Exception("Check pool fail...")
        else:
            logger.info('Check pool successfully...')

    def create_client(self, vbs_ip_list):
        """
        创建客户端
        :param vbs_ip_list: vbs节点ip list
        :return:
        """
        if vbs_ip_list:
            logger.info('create VBS client.')
            rsp_result, rsp_data = self.opr.create_vbs_client(vbs_ip_list)
            if rsp_result != 0:
                self.get_vbs_ip_list(vbs_ip_list)
                err_msg = "Failed to Create VBS client, Detail:[" \
                          "result:%s, ip:%s]%s" % \
                          (rsp_result, vbs_ip_list, rsp_data)
                logger.error(err_msg)
                raise Exception(err_msg)
            logger.info('Create VBS success. nodes:[%s]' % vbs_ip_list)

    def config_iscsi_port(self):
        iscsi_configed_count = 0
        for fsa in self.fsa_list:
            fsa_manage_ip = fsa.get('om_ip')
            rsp_result, rsp_data = self.opr.get_network_serive(
                fsa_manage_ip)
            fsa_storage_ip = self._get_iscsi_storage_ip(rsp_data)
            if not fsa_storage_ip:
                logger.error(
                    "fsa_ip= %s, storage ip is null. result=[%s] %s"
                    % (fsa_manage_ip, rsp_result, rsp_data))
                continue

            rsp_result, rsp_data = self.opr.set_iscsi_switch(fsa_manage_ip)
            if not rsp_data.get("successDetail"):
                err_msg = "Failed to config iscsi switch, fsa ip=%s" \
                          ", result=[%s] %s" % (fsa_manage_ip, rsp_result, rsp_data)
                logger.error(err_msg)
                raise Exception(err_msg)

            rsp_result, rsp_data = self.opr.set_iscsi_portal(fsa_manage_ip, fsa_storage_ip)
            if not rsp_data.get("successDetail"):
                error_code = rsp_data.get('detail')[0].get('errorCode')
                if error_code == 33760258:
                    iscsi_configed_count += 1
                    logger.info("The specified iSCSI IP address already exists on node[%s]." % fsa_manage_ip)
                    continue
                err_msg = "Failed to add iscsi portal, fsa ip=%s, " \
                          "result=%s" % (fsa_manage_ip,
                                         rsp_data)
                logger.error(err_msg)
                raise Exception(err_msg)

            iscsi_configed_count += 1
        if 0 == iscsi_configed_count:
            err_msg = "Failed to add iscsi portal for fsa node, " \
                      "count = 0"
            logger.error(err_msg)
            raise Exception(err_msg)
        logger.info('Config iscsi service success, fsa count=%d' %
                    iscsi_configed_count)

    @staticmethod
    def _get_iscsi_storage_ip(rsp_data):
        fsa_storage_ip = None
        for network_data in rsp_data:
            ip_addr_list = network_data.get('ip_address_list')
            if not ip_addr_list:
                continue
            for ip_addr in ip_addr_list:
                ip_usage = ip_addr.get('ip_usage')
                if not ip_usage:
                    continue
                ip_usage_str = ",".join(ip_usage)
                if 0 > ip_usage_str.find("storage_backend")\
                        and 0 > ip_usage_str.find("storage_frontend"):
                    continue
                fsa_storage_ip = ip_addr.get('ip_address')
        return fsa_storage_ip
