# -*-coding:utf-8-*-
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
import copy
import os
import pathlib
import shutil
import configparser
import subprocess
import time
import random
import string

from utils.business.param_util import ParamUtil
from utils.business.project_condition_utils import get_project_condition_boolean
from utils.DBAdapter.DBConnector import BaseOps
from utils.constant.path_constant import ProjectPluginsPath
from utils.client.FSPAuthClient import FSPAuthClient
from utils.Driver.CloudDC.OpenStack.config_cascading_kvm import ConfinCascadingKvm
import utils.common.log as logger
from utils.security.crypt import decrypt
from utils.common.ssh_util2 import Ssh
from plugins.DistributedStorage.utils.common.deploy_constant import DeployConstant
from plugins.DistributedStorage.logic.deploy_operate import DeployOperate
from plugins.DistributedStorage.logic.file_handle import FileHandle
from plugins.DistributedStorage.logic.sandbox_operate import SandBoxHandlerForDeploy
from plugins.DistributedStorage.implement.tc_config_kvm_resource_pool import ConfigKVMResourcePoolFather


class DistributedStorageArgs(object):
    def __init__(self, project_id, pod_id, args=None):
        self.project_id = project_id
        self.pod_id = pod_id
        self.args = args
        self.params = ParamUtil()
        self.db = BaseOps()

    def get_manage_storage_float_ip(self):
        """
        :function 获取管理存储浮动IP
        :param: pod_id
        :return: 返回float_ip，如果不存在，返回空
        """
        logger.info("Get ManageStorFB80 Parameters")
        manage_float_ip = self.params.get_value_from_cloudparam(
            self.pod_id, "DistributedStorageManage", "FSMOMFloatingIP")
        logger.info("Returned DistributeStorage manage storage floatIP[%s]" % manage_float_ip)
        return manage_float_ip

    def get_ha_manage_storage_float_ip(self):
        """
        :function 获取高可用备管理存储浮动IP
        :param: pod_id
        :return: 返回float_ip，如果不存在，返回空
        """
        logger.info("Get ManageStorFB80 Parameters")
        ha_manage_float_ip = self.params.get_value_from_cloudparam(
            self.pod_id, "DistributedStorageManage", "HAFSMOMFloatingIP")
        logger.info("Returned DistributeStorage manage storage floatIP[%s]" % ha_manage_float_ip)
        return ha_manage_float_ip

    def get_business_storage_float_ip(self):
        """
        :function 获取业务存储浮动IP
        :param: pod_id
        :return: 返回float_ip，如果不存在，返回空
        """
        logger.info("Get TenantStorFB80 Parameters")
        if get_project_condition_boolean(self.project_id, '(TenantStorFB80|TenantStorFBHCI80)&ProjectDeploy'):
            logger.info("Get (TenantStorFB80|TenantStorFBHCI80)&ProjectDeploy Parameters")
            business_float_ip = self.params.get_value_from_cloudparam(
                self.pod_id, "DistributedStorageBusiness", "FSMOMFloatingIP02")
        elif get_project_condition_boolean(self.project_id, 'TenantStorFB80&(ExpansionAZ_KVM|ExpansionAZ_BMS)'):
            logger.info("Get TenantStorFB80&(ExpansionAZ_KVM|ExpansionAZ_BMS) Parameters")
            business_float_ip = self.db.get_user_input_cloud_param_by_key(self.project_id, "expansion_new_fsm_float_ip")
        elif get_project_condition_boolean(self.project_id, 'TenantStorFB80&ExpansionServiceStorage'):
            logger.info("Get TenantStorFB80&ExpansionServiceStorage Parameters")
            business_float_ip = self.db.get_user_input_cloud_param_by_key(
                self.project_id, "expansion_fusionstorage_float_ip")
        elif get_project_condition_boolean(self.project_id,
                                           '((TenantStorFBReuse80|TenantStorHCIFS800Reuse)&ExpansionAZ_KVM)|'
                                           'ExpansionServiceStorage&(TenantStorNewPool|TenantStorNewNode)'):
            logger.info("Get ((TenantStorFBReuse80|TenantStorHCIFS800Reuse)&ExpansionAZ_KVM)"
                        "|ExpansionServiceStorage&(TenantStorNewPool|TenantStorNewNode) Parameters")
            business_float_ip = self.db.get_user_input_cloud_param_by_key(self.project_id, "expansion_az_fsm_float_ip")
        elif get_project_condition_boolean(self.project_id,
                                           '(ExpansionAZ_BMS&TenantStorFBReuse80)|'
                                           '(ExpansionComputeRes_KVMNode|ExpansionNetworkRes_NetworkNode)&'
                                           '(TenantStorFB80|TenantStorFBHCI80)|TenantStorFBPoolReuse80'):
            logger.info("Get (ExpansionAZ_BMS&TenantStorFBReuse80)|"
                        "(ExpansionComputeRes_KVMNode|ExpansionNetworkRes_NetworkNode)&"
                        "(TenantStorFB80|TenantStorFBHCI80)|TenantStorFBPoolReuse80 Parameters")
            business_float_ip = self.db.get_user_input_cloud_param_by_key(self.project_id, "reuse_fsm_float_ip")
        else:
            logger.info("Get other Parameters")
            business_float_ip = None
        logger.info("Returned DistributeStorage business storage floatIP[%s]" % business_float_ip)
        return business_float_ip

    def get_init_fsm_portal_pwd(self):
        """
        :function 获取初始的界面密码
        :param: pod_id
        :return: 返回float_ip，如果不存在，返回空
        """
        logger.info("Get  FSM default portal Parameters")
        init_fsm_portal_pwd = self.params.get_value_from_cloudparam(
            self.pod_id, "DistributedStorage", "DMPortalInitPassword")
        if not init_fsm_portal_pwd:
            logger.info("Failed to get DistributeStorage init fsm portal psw")
        else:
            logger.info("Succeed to get DistributeStorage init fsm portal psw")
        return init_fsm_portal_pwd

    def get_default_fsm_portal_pwd(self):
        """
        :function 获取默认的界面密码
        :param: pod_id
        :return: 返回float_ip，如果不存在，返回空
        """
        logger.info("Get  FSM default portal Parameters")
        default_portal_pwd = self.params.get_value_from_cloudparam(
            self.pod_id, "DistributedStorage", "FSMPortalPassword")
        if not default_portal_pwd:
            logger.info("Failed to get DistributeStorage default portal psw")
        else:
            logger.info("Succeed to get DistributeStorage default portal psw")
        return default_portal_pwd

    def get_default_fsm_fsadmin_pwd(self):
        """
        :function 获取默认的fsadmin密码
        :param: pod_id
        :return: 返回float_ip，如果不存在，返回空
        """
        logger.info("Get  FSM default portal Parameters")
        fsm_fsadmin_pwd = self.params.get_value_from_cloudparam(self.pod_id, "DistributedStorage", "FSMfsdminPassword")
        if not fsm_fsadmin_pwd:
            logger.info("Failed to get DistributeStorage fsm fsadmin psw")
        else:
            logger.info("Succeed to get DistributeStorage fsm fsadmin psw")
        return fsm_fsadmin_pwd

    def get_default_fsm_root_pwd(self):
        """
        :function 获取默认的root密码
        :param: pod_id
        :return: 返回float_ip，如果不存在，返回空
        """
        logger.info("Get  FSM default portal Parameters")
        fsm_root_pwd = self.params.get_value_from_cloudparam(self.pod_id, "DistributedStorage", "FSMrootPassword")
        if not fsm_root_pwd:
            logger.info("Failed to get DistributeStorage default fsm root psw")
        else:
            logger.info("Succeed to get DistributeStorage default fsm root psw")
        return fsm_root_pwd

    def get_new_fsm_fsadmin_pwd(self):
        """
        :function 获取默认的new fsadmin密码
        :param: pod_id
        :return: 返回float_ip，如果不存在，返回空
        """
        logger.info("Get  FSM default portal Parameters")
        new_fsm_fsadmin_pwd = self.db.get_user_input_cloud_param_by_key(self.project_id, "reuse_fsm_fsadmin_passwd")
        if not new_fsm_fsadmin_pwd:
            logger.info("Failed to get DistributeStorage default fsm new fsadmin psw")
        else:
            logger.info("Succeed to get DistributeStorage default fsm new fsadmin psw")
        return new_fsm_fsadmin_pwd

    def get_business_fsm_portal_pwd(self):
        """
        获取所有业务分离场景的业务存储fsm portal密码
           部署工程、扩az新建、IPSAN扩分布式存储，使用默认密码
           扩az复用，新增业务存储--新增存储节点/存储池，扩计算节点，扩计算az复用分布式存储，获取LLD表填写的密码
        """
        portal_pwd = self.db.get_value_from_cloudparam(self.pod_id, "DistributedStorage", "FSMPortalPassword")
        if get_project_condition_boolean(
                self.project_id,
                'ExpansionAZ_KVM&TenantStorFBPoolReuse80'
                '|TenantStorFB80&(ExpansionComputeRes_KVMNode|ExpansionNetworkRes_NetworkNode)'
                '|TenantStorFBReuse80&(ExpansionAZ_KVM|ExpansionAZ_BMS)'
                '|ExpansionServiceStorage&(TenantStorNewPool|TenantStorNewNode)'):
            portal_pwd = self.db.get_user_input_cloud_param_by_key(self.project_id, "reuse_fsm_admin_passwd")
        if not portal_pwd:
            logger.error('Failed to get fsm portal info')
        return portal_pwd

    def get_rep_local_admin_pwd(self):
        """
        全新建场景，使用默认密码，追加生产、灾备端使用LLD表填写的密码
        """
        # 追加生产端：
        exp_product = get_project_condition_boolean(
            self.project_id,
            'DRStorage_TFB_PD&(CSHAStorage_TFB|CSDRStorage_TFB)&DRStorage_TFB_Sep'
            '&(ExpansionAdCloudService|ExpansionServiceStorage)'
        )
        # 追加灾备端：
        exp_disaster = get_project_condition_boolean(
            self.project_id,
            '!DRStorage_TFB_PD&(CSHAStorage_TFB|CSDRStorage_TFB)&DRStorage_TFB_Sep'
            '&(ExpansionAdCloudService|ExpansionServiceStorage)'
        )
        if exp_product:
            local_admin_password = self.params.get_param_value(
                self.pod_id, "FusionStorageBlockReplication", 'produce_storage_fsm_admin_password')
        elif exp_disaster:
            local_admin_password = self.params.get_param_value(
                self.pod_id, "FusionStorageBlockReplication", 'disaster_storage_fsm_admin_password')
        else:
            local_admin_password = self.db.get_value_from_cloudparam(
                self.pod_id, "DistributedStorage", "FSMPortalPassword")
        if not local_admin_password:
            logger.error('Failed to get local admin info')
        return local_admin_password

    def get_rep_net_info(self, rep_index="1"):
        """
        获取复制网络信息
        :param rep_index:
        :return:
        """
        fs_args = dict()
        fs_args["port_name"] = "rep1" if rep_index == "1" else "rep2"
        fs_args["net_info"] = self.get_net_info_from_lld('fusionstorage_rep', 'DistributedStorageBusiness',
                                                         index=rep_index)
        fs_args["net_plane"] = 'replication_plane'
        fs_args["nic_bond_mode"] = 'active_standby'
        fs_args["vlan_flag"] = False
        fs_args["port_index"] = 1 if rep_index == "1" else 2
        fs_args["node_role"] = "rep"
        return fs_args

    def get_net_info_from_lld(self, network_name, condition="DistributedStorageBusiness", index="1"):
        param_util = ParamUtil()
        _tag = param_util.get_param_value(self.pod_id, condition, network_name + "_tag" + index)
        _vlan = param_util.get_param_value(self.pod_id, condition, network_name + "_vlan" + index)
        _vlan_id = param_util.get_param_value(self.pod_id, condition, network_name + "_vlan_id" + index)
        if _tag:
            vlan = _tag
        elif _vlan_id:
            vlan = _vlan_id
        else:
            vlan = _vlan

        ip_range = param_util.get_param_value(self.pod_id, condition, network_name + "_range" + index)
        if not ip_range:
            return {}

        net_info_dic = {
            "ip_start": ip_range.split("-")[0],
            "gateway": param_util.get_param_value(self.pod_id, condition, network_name + "_gateway" + index),
            "netmask": param_util.get_param_value(self.pod_id, condition, network_name + "_netmask" + index),
            "name": network_name,
            "vlan": vlan
        }

        return net_info_dic


class DistributedStorageTool(object):
    def __init__(self, project_id, pod_id, db):
        self.project_id = project_id
        self.pod_id = pod_id
        self.db = db
        logger.init('StorageTool Util Init')

    def get_fsc_cli_cert_file(self, return_path, float_ip, storage_info=None, storage_type=False):
        """
        获取 Dsware-Api 证书，在数据库先查老证书，有就不用新签发。对分布式场景，替换证书在外侧，此函数只返回最新证书。
        :param return_path:证书文件保存路径
        :param float_ip:分布式块存储浮动IP
        :param storage_info: 默认为None,表示该场景为分布式存储部署工程；其他场景调用接口需要传参，参数格式：
        {"float_ip": "xxx.xxx.xxx.xxx", "portal_init_pwd": "******", "portal_pwd": "******",
        "fsadmin_pwd": "******", "root_pwd": "******"}
        :param storage_type: 分布式存储场景标记符，其他场景不传入
        :return: dict{'ca_file': ca证书文件路径,
                     'cert_file': 服务证书文件路径,
                     'key_file': 私钥文件路径,
                     'password': 加密口令}
        """
        if storage_info is None:
            storage_info = self._get_storage_info(float_ip)
        else:
            storage_info["float_ip"] = float_ip

        if storage_type:
            return IssueDswareApiCert(return_path, storage_info).main()

        old_cert_file = GetOldFscli(self.project_id, self.pod_id, float_ip).main(return_path)

        return old_cert_file if old_cert_file else IssueDswareApiCert(return_path, storage_info).main()

    def get_fsc_cli_cert_file_from_remote_region(self, return_path, float_ip, storage_info=None):
        if storage_info is None:
            storage_info = self._get_storage_info(float_ip)
        else:
            storage_info["float_ip"] = float_ip

        return IssueDswareApiCertForOtherRegion(return_path, storage_info).main()

    def get_storage_float_ip(self, az_mode=None, reuse_mode=None, dc=None):
        """
        :param az_mode: 默认 None 表示所有，manager 表示管理存储， business 表示业务存储, rep表示复制
        :param reuse_mode: 默认 None 表示所有，reuse 表示复用， new 表示新建
        :param dc: 默认 None 表示未用管理高可用， master表示管理高可用的主dc，standy 表示管理高可用的备dc
        :return: [{"float_ip": "xxx.xxx.xxx.xxx", "portal_init_pwd": "******", "portal_pwd": "******",
                   "fsadmin_pwd": "******", "root_pwd": "******"}]
        """
        storage_infos = []
        fsm_pwd_dic = self._get_fsm_all_pwd_info()
        if not az_mode or az_mode == "manager":
            logger.info('Get manager storage info')
            self._get_master_storage_info(dc, fsm_pwd_dic, reuse_mode, storage_infos)
            self._get_standby_storage_info(dc, fsm_pwd_dic, reuse_mode, storage_infos)

        if not az_mode or az_mode == "business":
            logger.info('Get business storage info')
            self._get_business_storage_info(fsm_pwd_dic, reuse_mode, storage_infos)

        self._get_rep_storage_infos(az_mode, fsm_pwd_dic, storage_infos)
        return storage_infos

    def _get_business_storage_info(self, fsm_pwd_dic, reuse_mode, storage_infos):
        if not reuse_mode or reuse_mode == "new":
            logger.info('Get business storage info, reuse mode:{}'.format(reuse_mode))
            float_ip = self.db.get_user_input_cloud_param_by_key(self.project_id, "expansion_new_fsm_float_ip")
            if float_ip:
                storage_info = {"float_ip": float_ip, reuse_mode: "new"}
                storage_info.update(fsm_pwd_dic)
                storage_infos.append(storage_info)
            float_ip = self.db.get_user_input_cloud_param_by_key(
                self.project_id, "expansion_fusionstorage_float_ip")
            if float_ip:
                storage_info = {"float_ip": float_ip, reuse_mode: "new"}
                storage_info.update(fsm_pwd_dic)
                storage_infos.append(storage_info)
            float_ip = self.db.get_all_data_with_key_value(
                self.pod_id, "DistributedStorageBusiness").get('FSMOMFloatingIP02')
            if float_ip:
                storage_info = {"float_ip": float_ip}
                storage_info.update(fsm_pwd_dic)
                storage_infos.append(storage_info)
        if not reuse_mode or reuse_mode == "reuse":
            logger.info('Get business storage info, reuse mode:{}'.format(reuse_mode))
            float_ip = self.db.get_user_input_cloud_param_by_key(self.project_id, "expansion_az_fsm_float_ip")
            if float_ip:
                portal_pwd = self.db.get_user_input_cloud_param_by_key(self.project_id, "reuse_fsm_admin_passwd")
                storage_info = {"float_ip": float_ip, reuse_mode: "reuse"}
                storage_info.update(fsm_pwd_dic)
                storage_info["portal_pwd"] = portal_pwd
                storage_infos.append(storage_info)

            float_ip = self.db.get_user_input_cloud_param_by_key(self.project_id, "reuse_fsm_float_ip")
            if float_ip:
                portal_pwd = self.db.get_user_input_cloud_param_by_key(self.project_id, "reuse_fsm_admin_passwd")
                storage_info = {"float_ip": float_ip, reuse_mode: "reuse"}
                storage_info.update(fsm_pwd_dic)
                storage_info["portal_pwd"] = portal_pwd
                storage_infos.append(storage_info)

    def _get_master_storage_info(self, dc, fsm_pwd_dic, reuse_mode, storage_infos):
        logger.info('Get {} storage info, reuse mode:{}'.format(dc, reuse_mode))
        if not dc or dc == "master":
            if not reuse_mode or reuse_mode == "new":
                float_ip = self.db.get_all_data_with_key_value(
                    self.pod_id, "DistributedStorageManage").get('FSMOMFloatingIP')
                if float_ip:
                    storage_info = {"float_ip": float_ip, reuse_mode: "new"}
                    storage_info.update(fsm_pwd_dic)
                    storage_infos.append(storage_info)
            if not reuse_mode or reuse_mode == "reuse":
                self._get_dc001_storage_info(fsm_pwd_dic, reuse_mode, storage_infos)
                self._get_expansion_storage_info(fsm_pwd_dic, reuse_mode, storage_infos)

    def _get_expansion_storage_info(self, fsm_pwd_dic, reuse_mode, storage_infos):
        logger.info('Get expansion storage info, reuse mode:{}'.format(reuse_mode))
        float_ip = self.db.get_user_input_cloud_param_by_key(self.project_id, "expansion_fsm_float_ip")
        if float_ip:
            portal_pwd = self.db.get_user_input_cloud_param_by_key(
                self.project_id, "expansion_fs8_fsm_admin_passwd")
            storage_info = {"float_ip": float_ip, reuse_mode: "reuse"}
            storage_info.update(fsm_pwd_dic)
            storage_info["portal_pwd"] = portal_pwd
            storage_infos.append(storage_info)

    def _get_dc001_storage_info(self, fsm_pwd_dic, reuse_mode, storage_infos):
        logger.info('Get dc001 storage info, reuse mode:{}'.format(reuse_mode))
        float_ip = self.db.get_user_input_cloud_param_by_key(self.project_id,
                                                             "dc001_expansion_fsm_float_ip")
        if float_ip:
            storage_info = {"float_ip": float_ip, reuse_mode: "reuse"}
            storage_info.update(fsm_pwd_dic)
            storage_info["portal_pwd"] = self.db.get_user_input_cloud_param_by_key(
                self.project_id, "dc001_expansion_fsm_admin_passwd")
            storage_infos.append(storage_info)

    def _get_standby_storage_info(self, dc, fsm_pwd_dic, reuse_mode, storage_infos):
        if not dc or dc == "standby":
            if not reuse_mode or reuse_mode == "new":
                float_ip = self.db.get_all_data_with_key_value(
                    self.pod_id, "DistributedStorageManage").get('HAFSMOMFloatingIP')
                if float_ip:
                    storage_info = {"float_ip": float_ip, reuse_mode: "new"}
                    storage_info.update(fsm_pwd_dic)
                    storage_infos.append(storage_info)
            if not reuse_mode or reuse_mode == "reuse":
                float_ip = self.db.get_user_input_cloud_param_by_key(self.project_id,
                                                                     "dc002_expansion_fsm_float_ip")
                if float_ip:
                    storage_info = {"float_ip": float_ip, reuse_mode: "reuse"}
                    storage_info.update(fsm_pwd_dic)
                    storage_info["portal_pwd"] = self.db.get_user_input_cloud_param_by_key(
                        self.project_id, "dc002_expansion_fsm_admin_passwd")
                    storage_infos.append(storage_info)

    def _get_rep_storage_infos(self, az_mode, fsm_pwd_dic, storage_infos):
        logger.info('Get rep storage info')
        if not az_mode or az_mode == 'rep':
            produce_float_ip = self.db.get_user_input_cloud_param_by_key(self.project_id, "produce_storage_fsm_ip")
            if produce_float_ip:
                produce_storage_fsm_fsadmin_password = self.db.get_user_input_cloud_param_by_key(
                    self.project_id, "produce_storage_fsm_fsadmin_password")
                produce_storage_fsm_root_password = self.db.get_user_input_cloud_param_by_key(
                    self.project_id, "produce_storage_fsm_root_password")
                produce_storage_fsm_admin_password = self.db.get_user_input_cloud_param_by_key(
                    self.project_id, "produce_storage_fsm_admin_password")
                storage_info = {"float_ip": produce_float_ip,
                                "portal_init_pwd": fsm_pwd_dic.get("portal_init_pwd"),
                                "portal_pwd": produce_storage_fsm_admin_password,
                                "fsadmin_pwd": produce_storage_fsm_fsadmin_password,
                                "root_pwd": produce_storage_fsm_root_password,
                                "produce_storage_fsm_root_password": produce_storage_fsm_root_password,
                                "produce_storage_fsm_admin_password": produce_storage_fsm_admin_password,
                                "mode": "produce"}
                storage_infos.append(storage_info)
            disaster_float_ip = self.db.get_user_input_cloud_param_by_key(
                self.project_id, "disaster_tolerant_storage_fsm_ip")
            if disaster_float_ip:
                disaster_fsm_fsadmin_password = self.db.get_user_input_cloud_param_by_key(
                    self.project_id, "disaster_storage_fsm_fsadmin_password")
                disaster_fsm_root_password = self.db.get_user_input_cloud_param_by_key(
                    self.project_id, "disaster_tolerant_storage_fsm_root_password")
                disaster_fsm_admin_password = self.db.get_user_input_cloud_param_by_key(
                    self.project_id, "disaster_storage_fsm_admin_password")
                storage_info = {"float_ip": disaster_float_ip,
                                "portal_init_pwd": fsm_pwd_dic.get("portal_init_pwd"),
                                "portal_pwd": disaster_fsm_admin_password,
                                "fsadmin_pwd": disaster_fsm_fsadmin_password,
                                "root_pwd": disaster_fsm_root_password,
                                "disaster_tolerant_storage_fsm_root_password": disaster_fsm_root_password,
                                "disaster_storage_fsm_admin_password": disaster_fsm_admin_password,
                                "mode": "disaster"}
                storage_infos.append(storage_info)

    def _get_fsm_all_pwd_info(self):
        logger.info('Get fsm info')
        portal_init_pwd = self.db.get_value_from_cloudparam(self.pod_id, "DistributedStorage", "DMPortalInitPassword")
        portal_pwd = self.db.get_value_from_cloudparam(self.pod_id, "DistributedStorage", "FSMPortalPassword")
        fsadmin_pwd = self.db.get_value_from_cloudparam(self.pod_id, "DistributedStorage", "FSMfsdminPassword")
        root_pwd = self.db.get_value_from_cloudparam(self.pod_id, "DistributedStorage", "FSMrootPassword")
        fsadmin_pwd_new = self.db.get_user_input_cloud_param_by_key(self.project_id, "reuse_fsm_fsadmin_passwd")
        fsadmin_pwd = fsadmin_pwd_new if fsadmin_pwd_new else fsadmin_pwd
        pwd_dic = {"portal_init_pwd": portal_init_pwd,
                   "portal_pwd": portal_pwd,
                   "fsadmin_pwd": fsadmin_pwd,
                   "root_pwd": root_pwd}
        return pwd_dic

    def _get_storage_info(self, float_ip):
        ret = None
        storage_cluster_list = self.get_storage_float_ip()
        for storage_cluster in storage_cluster_list:
            if storage_cluster.get("float_ip") == float_ip:
                ret = storage_cluster
                break
        if ret is None:
            err_msg = "Failed to get storage_info, please make sure params correct!"
            logger.error(err_msg)
            raise Exception(err_msg)
        return ret


class IssueDswareApiCert:
    def __init__(self, save_path: str, storage_info: dict):
        self.save_path = save_path
        self.storage_info = storage_info
        self.cert_name = "dsware_api" + ''.join(random.choices(string.digits + string.ascii_letters, k=10))
        self.key_file_name = self.cert_name + ".key"
        self.csr_file_name = self.cert_name + ".csr"
        self.key_file = os.path.join(self.save_path, self.key_file_name)
        self.csr_file = os.path.join(self.save_path, self.csr_file_name)
        self.create_csr_script_path = "{}/DistributedStorage/tool/create_csr.sh".format(
            ProjectPluginsPath.project_plugins_path())
        self.ret_info = {
            'ca_file': os.path.join(self.save_path, "ca_file.ca"),
            'cert_file': os.path.join(self.save_path, "cert_file.cert"),
            'key_file': os.path.join(self.save_path, "key_file.ca")
        }
        self.opr = DeployOperate(float_ip=self.storage_info.get("float_ip"))

    @classmethod
    def get_encrypted_pwd(cls):
        plugin_path = ProjectPluginsPath.project_plugins_path()
        cfg_path = r"{}/DistributedStorage/Deploy/params/params.cfg".format(plugin_path)
        cfg = configparser.ConfigParser()
        cfg.read(cfg_path)
        return decrypt(cfg.get('FSMPortalPassword', 'param_value'))

    def main(self):
        logger.info("Create local dictionary:{}".format(self.save_path))
        FileHandle.create_tmp_dir(self.save_path, permission=0o700)

        logger.info("Get private key:{}".format(self.ret_info.get("key_file")))
        self.get_private_key()

        self.opr.login(DeployConstant.DM_LOGIN_USER, self.storage_info.get("portal_pwd"))

        logger.info("Get cert file:{}".format(self.ret_info.get("cert_file")))
        self.get_cert()

        logger.info("Get ca file:{}".format(self.ret_info.get("ca_file")))
        self.get_ca()

        logger.info("Get dsware_api Cert SUCCESS")
        return self.ret_info

    def get_private_key(self):
        self.ret_info["password"] = self.get_encrypted_pwd()
        cmd_list = ["/usr/bin/bash", self.create_csr_script_path,
                    self.ret_info.get("password"), self.save_path, self.cert_name]
        result = subprocess.Popen(cmd_list,
                                  shell=False,
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE)
        std_out, std_err = result.communicate(timeout=30)
        if result.returncode != 0:
            err_msg = "error:{}".format(str(std_err).replace(self.ret_info.get("password"), ""))
            logger.error(err_msg)
            raise Exception(err_msg)
        if not pathlib.Path(self.key_file).is_file():
            err_msg = "Get private key failed, {} is not exist".format(self.key_file)
            logger.error(err_msg)
            raise Exception(err_msg)
        pathlib.Path(self.csr_file).chmod(0o600)
        pathlib.Path(self.key_file).chmod(0o600)
        shutil.copy2(self.key_file, self.ret_info.get("key_file"))

    def get_cert(self):
        """
        登录存储  --  导入请求文件  -- 签发证书
        :return:
        """
        with open(self.csr_file, 'r', encoding="utf-8") as csr_file:
            csr_steam = csr_file.read()
        data = {
            "issuerCaName": "MicroService",
            "certName": self.cert_name,
            "validityPeriod": "7300",
            "digestAlgorithm": 0,
            "csrImportType": 1,
            "csrContent": csr_steam
        }
        tmp = copy.deepcopy(data)
        tmp["csrContent"] = "***"
        logger.info("request info:{}".format(tmp))
        res = self.opr.issue_cert(data)
        logger.info("response:{}".format(res))
        if res.get("result").get("code") != 0:
            raise Exception(res)

        time.sleep(20)

        logger.info("export cert")
        res = self.opr.export_cert(self.cert_name)
        logger.info("export cert response:{}".format(res))
        if res.get("result").get("code") != 0:
            raise Exception(res)
        data = res.get("data")

        time.sleep(5)

        logger.info("Download Cert")
        cert_content = self.opr.download_cert(data.get("certPath"), data.get("exportCertName"))
        FileHandle.dump_content(self.ret_info.get("cert_file"), cert_content, permission=0o600)
        logger.info("Get Cert SUCCESS")

    def get_ca(self):
        logger.info("export CA")
        res = self.opr.export_ca("MicroService")
        logger.info("export CA response:{}".format(res))
        if res.get("result").get("code") != 0:
            raise Exception(res)
        data = res.get("data")

        time.sleep(5)

        logger.info("Download CA")
        cert_content = self.opr.download_ca(data.get("certPath"), data.get("certName"))
        FileHandle.dump_content(self.ret_info.get("ca_file"), cert_content, permission=0o600)
        logger.info("Get CA SUCCESS")


class GetOldFscli:
    def __init__(self, project_id, pod_id, float_ip):
        self.project_id = project_id
        self.pod_id = pod_id
        self.float_ip = float_ip
        self.db = BaseOps()

    # 在cps上查老证书
    def main(self, return_path):
        ret_info = {
            'ca_file': os.path.join(return_path, "ca_file.ca"),
            'cert_file': os.path.join(return_path, "cert_file.cert"),
            'key_file': os.path.join(return_path, "key_file.ca")}

        webui_client = FSPAuthClient.get_cps_web_client(self.db, self.project_id, self.pod_id)
        obj = ConfinCascadingKvm(webui_client)
        resource_pool_data = obj.get_kvm_resource_pool()
        old_fscli_cfg = ConfigKVMResourcePoolFather(self.project_id, self.pod_id).get_old_fscli_cfg(
            self.float_ip, resource_pool_data)

        if not old_fscli_cfg:
            return {}

        logger.info("Create local dictionary:{}".format(return_path))
        FileHandle.create_tmp_dir(return_path, permission=0o700)

        ret_info["password"] = IssueDswareApiCert.get_encrypted_pwd()

        logger.info("Get private key:{}".format(ret_info.get("key_file")))
        FileHandle.dump_content(ret_info.get('key_file'),
                                old_fscli_cfg.get("fsc_cli_connect_key", "").encode('utf-8'), permission=0o600)

        logger.info("Get cert file:{}".format(ret_info.get("cert_file")))
        FileHandle.dump_content(ret_info.get('cert_file'),
                                old_fscli_cfg.get("fsc_cli_connect_cert", "").encode('utf-8'), permission=0o600)

        logger.info("Get ca file:{}".format(ret_info.get("ca_file")))
        FileHandle.dump_content(ret_info.get("ca_file"),
                                old_fscli_cfg.get("fsc_cli_connect_ca", "").encode('utf-8'), permission=0o600)

        logger.info("Get dsware_api Cert SUCCESS")
        return ret_info


class IssueDswareApiCertForOtherRegion(IssueDswareApiCert):
    def __init__(self, save_path: str, storage_info: dict):
        super().__init__(save_path, storage_info)
        self.root_pwd = storage_info.get("root_pwd")
        self.enabled_sandbox_ip = []
        self.storage_info["dm_update_pwd"] = self.storage_info.get("portal_pwd")
        self.storage_info["fsm_root_pwd"] = self.storage_info.get("root_pwd")
        self.float_ip = self.storage_info.get("float_ip")
        self.sandbox_handle = SandBoxHandlerForDeploy(self.storage_info)
        self.sandbox_status = False

    def main(self):
        logger.info("Create local dictionary:{}".format(self.save_path))
        FileHandle.create_tmp_dir(self.save_path, permission=0o700)
        sandbox_initial_status = self.sandbox_handle.sandbox_initial_status
        logger.info("sandbox initial state of FSM:{}".format(self.sandbox_handle.sandbox_initial_status))
        for status in sandbox_initial_status.values():
            if status == 0:
                self.sandbox_status = True
        if self.sandbox_status:
            self.sandbox_handle.disable_fsm_sandbox()

        try:
            self.get_cert_file()
            logger.info("Get Cert SUCCESS")
            return self.ret_info
        except Exception as err:
            error_msg = "Get cert file failed"
            logger.error(error_msg)
            raise Exception(error_msg) from err
        finally:
            if self.sandbox_status:
                self.sandbox_handle.enable_fsm_sandbox()

    def get_cert_file(self):
        ssh_client = self.create_ssh_root_client(self.float_ip,
                                                           "fsadmin",
                                                           self.storage_info.get("fsadmin_pwd"),
                                                           self.storage_info.get("root_pwd"))
        get_cert_cmd = "su - omm -s /bin/bash -c '/opt/dsware/manager/script/ks2pem.sh'"
        expect_return = "Please input password"
        Ssh.ssh_send_command(ssh_client, get_cert_cmd, expect_return, 10)
        self.ret_info["password"] = self.get_encrypted_pwd()
        expect_return = "0 entries failed or cancelled"
        Ssh.ssh_send_command(ssh_client, self.ret_info["password"], expect_return, 30)
        logger.info("Success to create cert file.")
        chmod_cmd = f"chmod 640 {DeployConstant.CERT_DIR}*"
        Ssh.ssh_send_command(ssh_client, chmod_cmd, "#", 10)

        logger.info('Downloading Certificates and CA Certificates')
        Ssh.get_file(self.float_ip, "fsadmin", self.storage_info.get("fsadmin_pwd"),
                     DeployConstant.CERT_DIR+DeployConstant.KEY_FILE,
                     self.ret_info.get("key_file"))
        Ssh.get_file(self.float_ip, "fsadmin", self.storage_info.get("fsadmin_pwd"),
                     DeployConstant.CERT_DIR+DeployConstant.CA_FILE,
                     self.ret_info.get("ca_file"))
        Ssh.get_file(self.float_ip, "fsadmin", self.storage_info.get("fsadmin_pwd"),
                     DeployConstant.CERT_DIR+DeployConstant.CERT_FILE,
                     self.ret_info.get("cert_file"))

        if ssh_client['_channel'].closed:
            ssh_client = self.create_ssh_root_client(self.float_ip,
                                                               "fsadmin",
                                                               self.storage_info.get("fsadmin_pwd"),
                                                               self.storage_info.get("root_pwd"))
        rm_cmd = f"rm -rf {DeployConstant.CERT_DIR}"
        Ssh.ssh_send_command(ssh_client, rm_cmd, "#", 10)

    @staticmethod
    def create_ssh_root_client(host_ip, user, passwd, root_pwd):
        def su_root():
            cmd_res = Ssh.ssh_send_command(ssh_client, 'su -', 'assword:', 20)
            logger.info("exe cmd[su root] result:%s" % (str(cmd_res)))

            cmd_res = Ssh.ssh_send_command(ssh_client, root_pwd, '#', 20)
            logger.info("exe cmd[#] result:%s" % (str(cmd_res)))

            cmd_res = Ssh.ssh_send_command(ssh_client, 'TMOUT=0', '#', 20)
            logger.info("exe cmd[TMOUT=0] result:%s" % (str(cmd_res)))
        try:
            ssh_client = Ssh.ssh_create_client(host_ip, user, passwd)
        except Exception as e:
            create_err_msg = "Failed to connect host using user %s, omip:%s, err:%s" % (user, host_ip, str(e))
            logger.error(create_err_msg)
            raise Exception(create_err_msg) from e
        try:
            su_root()
        except Exception as e:
            switch_err_msg = "Failed to switch to root user, omip:%s, err:%s" % (host_ip, str(e))
            logger.error(switch_err_msg)
            if ssh_client:
                Ssh.ssh_close(ssh_client)
            raise Exception(switch_err_msg) from e
        return ssh_client


