#!/usr/bin/python
# -*- coding: UTF-8 -*-
import traceback
from json.decoder import JSONDecodeError
from plugins.DistributedStorage.utils.client.RestClient import RestClient
from plugins.DistributedStorage.utils.common.DeployConstant import DeployConstant
from plugins.DistributedStorage.utils.client.ResponseParse import ResponseParse
from utils.common.exception import HCCIException
import utils.common.log as logger


class DeployOperate(object):
    def __init__(self, fs_info=None, float_ip=None):
        if fs_info:
            self.fs_info = fs_info
        if not float_ip:
            self.float_ip = self.fs_info.get("float_ip")
        else:
            self.float_ip = float_ip
        self.port = DeployConstant.PORT
        self.rest_client = RestClient(self.float_ip)
        self.sys_esn = None

    def first_login(self, username, old_passwd, update_passwd):
        try:
            res = self.rest_client.login(username, old_passwd)
        except Exception as e:
            raise HCCIException(626067, str(e))
        result = ResponseParse(res)
        status_code, error_code, error_des = result.get_res_code()
        if status_code == 200 and error_code == 0:
            token = result.get_login_token()
            self.sys_esn = result.get_system_esn()
            self.rest_client.set_cookie(token)
            res = self.modify_init_pwd(username, old_passwd, update_passwd)
            status_code, error_code, error_des = res.get_res_code()
            if error_code != 0:
                logger.error("Failed to modify original password at DeviceManager[%s:%s]. Detail:[%s]"
                             % (self.float_ip, self.port, error_code))
                logger.error("modify password error description: %s" % error_des)
                raise HCCIException(626068, str(error_code))
        else:
            logger.error("Failed to login DeviceManager for first time[%s:%s]. Detail:[%s]"
                         % (self.float_ip, self.port, error_code))
            logger.error("first login error description: %s" % error_des)

        status_code, error_code, error_des = self.login(username, update_passwd)
        if status_code != 200 or error_code != 0:
            logger.error("Failed to login DeviceManager[%s:%s]. Detail:[%s]" % (self.float_ip, self.port, error_code))
            logger.error("login error description: %s" % error_des)
            raise HCCIException(626067, str(error_code))
        return error_code

    def login(self, username, password, keep_session=False):
        try:
            res = self.rest_client.login(username, password, keep_session)
        except Exception as e:
            raise HCCIException(626067, str(e))
        result = ResponseParse(res)
        status_code, error_code, error_des = result.get_res_code()
        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 HCCIException(626067, err_msg)
        token = result.get_login_token()
        self.sys_esn = result.get_system_esn()
        self.rest_client.set_cookie(token)
        return status_code, error_code, error_des

    def login_out(self, username, password):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.LOGIN_OUT
        res = self.rest_client.normal_request(url, 'delete')
        result = ResponseParse(res)
        return result

    def logout(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.LOGOUT
        try:
            self.rest_client.normal_request(url, 'delete')
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error("logout failed, error: %s" % str(e))

    def modify_init_pwd(self, username, old_pwd, upd_pwd):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.MODIFY_PWD % self.sys_esn
        data = {"ID": username,
                "PASSWORD": upd_pwd,
                "OLDPASSWORD": old_pwd}
        try:
            res = self.rest_client.normal_request(url, 'put', data)
        except Exception as e:
            raise HCCIException(626068, str(e))
        result = ResponseParse(res)
        return result

    def get_license_information(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.GET_LICENSE_INFORMATION \
              % self.sys_esn
        try:
            res = self.rest_client.normal_request(url, 'get')
        except Exception as e:
            raise HCCIException(626068, str(e))
        result = ResponseParse(res)
        return result

    def node_check_validity(self, rest_method, node_list, timeout=None):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.NODES_CHECK_VALIDITY
        try:
            res = self.rest_client.normal_request(url, rest_method, node_list, timeout=timeout)
        except Exception as e:
            raise HCCIException(626097, str(e))
        result = ResponseParse(res)
        return result

    def add_servers(self, rest_method, node_list, timeout=None):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.ADD_SERVERS
        try:
            res = self.rest_client.normal_request(url, rest_method, node_list, timeout=timeout)
        except Exception as e:
            raise HCCIException(626069, str(e))
        result = ResponseParse(res)
        return result

    def nodes_restore_factory(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.NODES_RESTORE_FACTORY
        try:
            res = self.rest_client.normal_request(url, "post")
        except Exception as e:
            raise HCCIException(626098, str(e))
        result = ResponseParse(res)
        return result

    def deploy_service(self, node_list, service_type=all):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.DEPLOY_SERVICE
        if service_type == "agent":
            deploy_info = {'service_type': "agent", 'node_ip_set': node_list}
        else:
            deploy_info = {'service_type': "all", 'node_ip_set': node_list}
        try:
            res = self.rest_client.normal_request(url, "post", deploy_info)
        except Exception as e:
            raise HCCIException(626070, str(e))
        result = ResponseParse(res)
        return result

    def deploy_service_retry(self, node_list, service_type=all):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.DEPLOY_SERVICE_RETRY
        if service_type == "agent":
            deploy_info = {'service_type': "agent", 'node_ip_set': node_list}
        else:
            deploy_info = {'service_type': "all", 'node_ip_set': node_list}
        try:
            res = self.rest_client.normal_request(url, "put", deploy_info)
        except Exception as e:
            raise HCCIException(626070, str(e))
        result = ResponseParse(res)
        return result

    def query_task_status(self, service_type=all, timeout=None):
        if service_type == "agent":
            url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.DEPLOY_SERVICE_TASK \
                  + '?service_type=agent'
        else:
            url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.DEPLOY_SERVICE_TASK \
                  + '?service_type=all'
        res = self.rest_client.normal_request(url, "get", timeout=timeout)
        result = ResponseParse(res)
        return result

    def query_deploy_servers(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.DEPLOY_MANAGER_SERVERS
        res = self.rest_client.normal_request(url, "get")
        result = ResponseParse(res)
        return result

    def query_cluster_servers(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CLUSTER_SERVERS
        res = self.rest_client.normal_request(url, "get")
        result = ResponseParse(res)
        return result

    def set_net_plane(self, notwork_list, net_type, scenario='initialization', bond_mode='', protocal='TCP'):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.NET_PLATFORM
        net_info = {'bond_mode': bond_mode,
                    'ip_list': notwork_list,
                    'network_type': net_type,
                    'transfer_protocol': protocal,
                    'scenario': scenario}
        try:
            res = self.rest_client.normal_request(url, 'put', net_info)
            resp = res.json()
            err_msg = 'put %s cmd. Detail: %s' % (url, resp)
            if res.status_code < 200 or res.status_code > 299:
                logger.error(err_msg)
                raise HCCIException(626278, url, err_msg)
            else:
                logger.info(err_msg)
            rsp_result = resp.get('result')
            rsp_data = resp.get('data')
        except Exception as e:
            raise HCCIException(626071, str(e))
        return rsp_result, rsp_data

    def get_storage_frontend_net_plane(self, net_type):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.NET_PLATFORM + "?network_type=" \
              + net_type
        try:
            res = self.rest_client.normal_request(url, 'get')
        except Exception as e:
            raise HCCIException(626071, str(e))
        result = ResponseParse(res)
        return result

    def get_storage_net_plane(self, net_type):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.NET_PLATFORM + "?network_type=" \
              + net_type
        try:
            res = self.rest_client.normal_request(url, 'get')
            result = ResponseParse(res)
            rsp_code, rsp_result, rsp_data = result.get_rsp_data()
            if rsp_code != 0:
                err_msg = 'Failed to get net. Detail:[result:%s,' \
                          'code:%s]%s' % (rsp_code, rsp_result, rsp_data)
                logger.error(err_msg)
                raise Exception(err_msg)
        except Exception as e:
            raise HCCIException(626071, str(e))
        return rsp_result, rsp_data

    def config_net_validity(self, network_type, node_list):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + '/api/v2/network_service/validity'
        node_ips = list()
        for node in node_list:
            node_ip = {'management_internal_ip': node}
            node_ips.append(node_ip)
        net_info = {'network_type': network_type,
                    'servers': node_ips}
        res = self.rest_client.normal_request(url, 'post', net_info)
        result = ResponseParse(res)
        return result

    def validity_net(self, network_type, node_list):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + '/api/v2/network_service/validity'
        try:
            node_ips = list()
            for node in node_list:
                node_ip = {'management_internal_ip': node}
                node_ips.append(node_ip)
            net_info = {'network_type': network_type,
                        'servers': node_ips}
            res = self.rest_client.normal_request(url, 'post', net_info)
            resp = res.json()
            err_msg = 'put %s cmd. Detail: %s' % (url, resp)
            if res.status_code < 200 or res.status_code > 299:
                logger.error(err_msg)
                raise HCCIException(626278, url, err_msg)
            else:
                logger.info(err_msg)
            rsp_result = resp.get('result')
            rsp_data = resp.get('data')
        except Exception as e:
            raise HCCIException(626072, str(e))
        return rsp_result, rsp_data

    def add_cluster_node(self, node_id_list):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CLUSTER_NODE
        node_data = {"in_cluster": node_id_list}
        res = self.rest_client.normal_request(url, 'post', node_data)
        result = ResponseParse(res)
        return result

    def create_cluster(self, cluster_name, node_info_list):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CREATE_CLUSTER
        cluster_info = {"clusterName": cluster_name,
                        "serverList": node_info_list}
        try:
            res = self.rest_client.normal_request(url, 'post', cluster_info)
        except Exception as e:
            raise HCCIException(626072, str(e))
        result = ResponseParse(res)
        return result

    def delete_manage_cluster(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.DELETE_MANAGE_CLUSTER
        try:
            cluster_info = None
            res = self.rest_client.normal_request(url, 'post', cluster_info)
            result = res.json()
        except Exception as e:
            raise HCCIException(626072, str(e))
        return result

    def query_manage_cluster(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.QUERY_MANAGE_CLUSTER
        try:
            res = self.rest_client.normal_request(url, 'get')
            result = ResponseParse(res)
            status_code, error_code, error_des = result.get_query_code()
            if status_code != 0:
                err_msg = 'Failed to query cluster. Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
                logger.error(err_msg)
                raise Exception(err_msg)
        except Exception as e:
            raise HCCIException(626073, str(e))
        return result

    def get_manage_cluster(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.QUERY_MANAGE_CLUSTER
        try:
            res = self.rest_client.normal_request(url, 'get')
            resp = res.json()
            err_msg = 'put %s cmd. Detail: %s' % (url, resp)
            if res.status_code < 200 or res.status_code > 299:
                logger.error(err_msg)
                raise HCCIException(626278, url, err_msg)
            else:
                logger.info(err_msg)
            rsp_result = resp.get('result')
            rsp_data = resp
        except Exception as e:
            raise HCCIException(626073, str(e))
        return rsp_result, rsp_data

    def set_globalparam(self, parameter_list):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.SET_GLOBALPARAM
        globalparam = {'opType': 'modify',
                       'parameter': parameter_list}
        try:
            res = self.rest_client.normal_request(url, 'post', globalparam)
            result = ResponseParse(res)
            error_code, detail = result.get_query_detail()
            if error_code != 0:
                err_msg = 'Failed to disable global parameter %s. ' \
                          'Detail:[code:%s]%s' % (parameter_list, error_code, detail)
                logger.error(err_msg)
                raise Exception(err_msg)
        except Exception as e:
            raise HCCIException(626073, str(e))
        return result

    def disable_dedup_compress(self):
        compression_parameter_list = list()
        compression_param = {'paraName': 'compression_function_switch',
                             'value': '0'}
        compression_parameter_list.append(compression_param)
        self.set_globalparam(compression_parameter_list)

        deduplication_parameter_list = list()
        deduplication_param = {'paraName': 'deduplication_function_switch',
                               'value': '0'}
        deduplication_parameter_list.append(deduplication_param)
        self.set_globalparam(deduplication_parameter_list)

    def scan_server_media(self, node_ip_list):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.SCAN_SERVER_MEDIA
        node_info = {"nodeIpList": node_ip_list}
        try:
            res = self.rest_client.normal_request(url, 'post', node_info)
            result = ResponseParse(res)
            status_code, error_code, error_des = result.get_query_code()
            if status_code != 0:
                err_msg = 'Failed to scan server media. Detail:[result:%s,code:%s]%s' % (status_code, error_code,
                                                                                         error_des)
                logger.error(err_msg)
                raise Exception(err_msg)
        except Exception as e:
            raise HCCIException(626074, str(e))
        return result

    def create_pool(self, pool_data):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CREATE_POOL
        try:
            res = self.rest_client.normal_request(url, 'post', pool_data)
        except Exception as e:
            raise HCCIException(626075, str(e))
        result = ResponseParse(res)
        return result

    def expand_pool(self, pool_data):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.EXPAND_POOL
        try:
            res = self.rest_client.normal_request(url, 'post', pool_data)
        except Exception as e:
            raise HCCIException(626075, str(e))
        result = ResponseParse(res)
        return result

    def query_all_disk(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.QUERY_ALL_DISK
        try:
            res = self.rest_client.normal_request(url, 'get')
            reslut = ResponseParse(res)
            status_code, error_code, error_des = reslut.get_query_code()
            if status_code != 0:
                err_msg = 'Failed to query cluster. Detail:[result:%s,code:%s]%s' % (status_code, error_code, error_des)
                logger.error(err_msg)
                raise Exception(err_msg)
        except Exception as e:
            raise HCCIException(626076, str(e))
        return reslut

    def query_task_info(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.QUERY_TASK_INFO
        try:
            res = self.rest_client.normal_request(url, 'get')
            reslut = ResponseParse(res)
            status_code, error_code, error_des = reslut.get_query_code()
            if status_code != 0:
                err_msg = 'Failed to query task info. Detail:[result:%s,code:%s]%s' % (status_code, error_code,
                                                                                       error_des)
                logger.error(err_msg)
                raise Exception(err_msg)
        except Exception as e:
            raise HCCIException(626077, str(e))
        return reslut

    def query_storage_pool(self, pool_id=None):
        if not pool_id:
            url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.QUERY_STORAGE_POOL
        else:
            url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.QUERY_STORAGE_POOL \
                  + "?poolId=" + pool_id
        try:
            res = self.rest_client.normal_request(url, 'get')
            reslut = ResponseParse(res)
            status_code, error_code, error_des = reslut.get_query_code()
            if status_code != 0:
                err_msg = 'Failed to query task info. Detail:[result:%s,code:%s]%s' % (status_code, error_code,
                                                                                       error_des)
                logger.error(err_msg)
                raise Exception(err_msg)
        except Exception as e:
            raise HCCIException(626078, str(e))
        return reslut

    def get_storage_pool(self, pool_id=None):
        if not pool_id:
            url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.QUERY_STORAGE_POOL
        else:
            url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.QUERY_STORAGE_POOL \
                  + "?poolId=" + pool_id
        try:
            res = self.rest_client.normal_request(url, 'get')
            resp = res.json()
            err_msg = 'put %s cmd. Detail: %s' % (url, resp)
            if res.status_code < 200 or res.status_code > 299:
                logger.error(err_msg)
                raise HCCIException(626278, url, err_msg)
            else:
                logger.info(err_msg)
            rsp_result = resp.get('result')
            rsp_data = resp
        except Exception as e:
            raise HCCIException(626078, str(e))
        return rsp_result, rsp_data

    def query_storage_node_by_pool_id(self, pool_id):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.QUERY_STORAGE_NODE_INFO \
              + '?poolId=' + pool_id
        try:
            res = self.rest_client.normal_request(url, 'get')
            result = ResponseParse(res)
            status_code, error_code, error_des = result.get_query_code()
            if status_code != 0:
                err_msg = 'Failed to query storage node info. Detail:[result:%s,code:%s]%s' % (status_code, error_code,
                                                                                               error_des)
                logger.error(err_msg)
                raise Exception(err_msg)
        except Exception as e:
            raise HCCIException(626076, str(e))
        return result

    def create_client(self, node_ip_list, node_type=0):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CREATE_CLIENT
        server_list = [{"nodeMgrIp": x, "nodeType": node_type} for x in node_ip_list]
        client_data = {"servers": server_list}
        try:
            res = self.rest_client.normal_request(url, 'post', client_data)
        except Exception as e:
            raise HCCIException(626079, str(e))
        result = ResponseParse(res)
        return result

    def create_vbs_client(self, node_ip_list):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CREATE_CLIENT
        try:
            server_list = [{"nodeMgrIp": x, "nodeType": 0} for x in
                           node_ip_list]
            client_data = {"servers": server_list}
            res = self.rest_client.normal_request(url, 'post', client_data)
            resp = res.json()
            err_msg = 'put %s cmd. Detail: %s' % (url, resp)
            if res.status_code < 200 or res.status_code > 299:
                logger.error(err_msg)
                raise HCCIException(626278, url, err_msg)
            else:
                logger.info(err_msg)
            rsp_result = resp.get('result')
            rsp_data = resp
        except Exception as e:
            raise HCCIException(626079, str(e))
        return rsp_result, rsp_data

    def clear(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CLEAR
        try:
            res = self.rest_client.normal_request(url, 'delete')
        except Exception as e:
            raise HCCIException(626080, str(e))
        result = ResponseParse(res)
        return result

    def set_time_zone(self, time_zone):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.SET_TIME_ZONE
        data = {"time_zone_name": time_zone}
        try:
            res = self.rest_client.normal_request(url, 'put', data)
        except Exception as e:
            raise HCCIException(626099, str(e))
        result = ResponseParse(res)
        return result

    def put_time_zone(self, time_zone):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.SET_TIME_ZONE
        data = {"time_zone_name": time_zone}
        try:
            res = self.rest_client.normal_request(url, 'put', data)
            resp = res.json()
            err_msg = 'put %s cmd. Detail: %s' % (url, resp)
            if res.status_code < 200 or res.status_code > 299:
                logger.error(err_msg)
                raise HCCIException(626278, url, err_msg)
            else:
                logger.info(err_msg)
            rsp_result = resp.get('result')
            rsp_data = resp.get('data')
        except Exception as e:
            raise HCCIException(626099, str(e))
        return rsp_result, rsp_data

    def check_ntp_server(self, ntp_server):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CHECK_NTP_SERVER % self.sys_esn
        data = {"CMO_SYS_NTP_CLNT_CONF_SERVER_IP": ntp_server}
        try:
            res = self.rest_client.normal_request(url, 'put', data)
        except Exception as e:
            raise HCCIException(626100, str(e))
        result = ResponseParse(res)
        return result

    def valid_ntp_server(self, ntp_server):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CHECK_NTP_SERVER % self.sys_esn
        data = {"CMO_SYS_NTP_CLNT_CONF_SERVER_IP": ntp_server}
        try:
            res = self.rest_client.normal_request(url, 'put', data)
            resp = res.json()
            err_msg = 'put %s cmd. Detail: %s' % (url, resp)
            if res.status_code < 200 or res.status_code > 299:
                logger.error(err_msg)
                raise HCCIException(626278, url, err_msg)
            else:
                logger.info(err_msg)
            rsp_result = resp.get('result')
            rsp_data = resp.get('data')
        except Exception as e:
            raise HCCIException(626100, str(e))
        return rsp_result, rsp_data

    def set_ntp_server(self, ntp_server):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.SET_NTP_SERVER % self.sys_esn
        data = {"CMO_SYS_NTP_CLNT_CONF_SWITCH": 1,
                "CMO_SYS_NTP_CLNT_CONF_SERVER_IP": ntp_server,
                "CMO_SYS_NTP_CLNT_CONF_AUTH_SWITCH": 0}
        try:
            res = self.rest_client.normal_request(url, 'put', data)
        except Exception as e:
            raise HCCIException(626101, str(e))
        result = ResponseParse(res)
        return result

    def put_ntp_server(self, ntp_server):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.SET_NTP_SERVER % self.sys_esn
        data = {"CMO_SYS_NTP_CLNT_CONF_SWITCH": 1,
                "CMO_SYS_NTP_CLNT_CONF_SERVER_IP": ntp_server,
                "CMO_SYS_NTP_CLNT_CONF_AUTH_SWITCH": 0}
        try:
            res = self.rest_client.normal_request(url, 'put', data)
            resp = res.json()
            err_msg = 'put %s cmd. Detail: %s' % (url, resp)
            if res.status_code < 200 or res.status_code > 299:
                logger.error(err_msg)
                raise HCCIException(626278, url, err_msg)
            else:
                logger.info(err_msg)
            rsp_result = resp.get('result')
            rsp_data = resp.get('data')
        except Exception as e:
            raise HCCIException(626101, str(e))
        return rsp_result, rsp_data

    def query_network_serive(self, manage_ip):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.NET_SERVICE
        data = {"servers": [{"management_internal_ip": manage_ip}]}
        res = self.rest_client.normal_request(url, 'post', data)
        result = ResponseParse(res)
        return result

    def get_network_serive(self, manage_ip):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.NET_SERVICE
        try:
            data = {"servers": [{"management_internal_ip": manage_ip}]}
            res = self.rest_client.normal_request(url, 'post', data)
            resp = res.json()
            err_msg = 'put %s cmd. Detail: %s' % (url, resp)
            if res.status_code < 200 or res.status_code > 299:
                logger.error(err_msg)
                raise HCCIException(626278, url, err_msg)
            else:
                logger.info(err_msg)
            rsp_result = resp.get('result')
            rsp_data = resp.get('data')
        except Exception as e:
            raise HCCIException(626101, str(e))
        return rsp_result, rsp_data

    def query_network_servers(self, manage_ip=None, net_type=None):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.NET_SERVICE
        try:
            data = dict()
            if net_type:
                net_type_filter = {"network_type": net_type}
                data.update(net_type_filter)
            if manage_ip:
                ip_filter = {"servers": [{"management_internal_ip": manage_ip}]}
                data.update(ip_filter)
            res = self.rest_client.normal_request(url, 'post', data)
            result = ResponseParse(res)
            rsp_code, rsp_result, rsp_data = result.get_rsp_data()
            if rsp_code != 0:
                err_msg = 'Failed to get net servers. Detail:[result:%s,' \
                          'code:%s]%s' % (rsp_code, rsp_result, rsp_data)
                logger.error(err_msg)
                raise Exception(err_msg)
        except Exception as e:
            raise HCCIException(626071, str(e))
        return rsp_result, rsp_data

    def config_iscsi_switch(self, manage_ip):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CONFIG_ISCSI_SWITCH
        data = {"ips": [manage_ip],
                "switch": 0}
        res = self.rest_client.normal_request(url, 'post', data)
        result = ResponseParse(res)
        return result

    def set_iscsi_switch(self, manage_ip):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CONFIG_ISCSI_SWITCH
        try:
            data = {"ips": [manage_ip],
                    "switch": 0}
            res = self.rest_client.normal_request(url, 'post', data)
            resp = res.json()
            err_msg = 'post %s cmd. Detail: %s' % (url, resp)
            if res.status_code < 200 or res.status_code > 299:
                logger.error(err_msg)
                raise HCCIException(626278, url, err_msg)
            else:
                logger.info(err_msg)
            rsp_result = resp.get('result')
            rsp_data = resp
        except Exception as e:
            raise HCCIException(626101, str(e))
        return rsp_result, rsp_data

    def add_iscsi_portal(self, manage_ip, storage_ip, port="3266"):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.ADD_ISCSI_PORTAL
        data = {"iscsiIp": storage_ip,
                "iscsiPort": port,
                "nodeMgrIps": [manage_ip]}

        res = self.rest_client.normal_request(url, 'post', data)
        result = ResponseParse(res)
        return result

    def set_iscsi_portal(self, manage_ip, storage_ip, port="3266"):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.ADD_ISCSI_PORTAL
        try:
            data = {"iscsiIp": storage_ip,
                    "iscsiPort": port,
                    "nodeMgrIps": [manage_ip]}

            res = self.rest_client.normal_request(url, 'post', data)
            resp = res.json()
            err_msg = 'post %s cmd. Detail: %s' % (url, resp)
            if res.status_code < 200 or res.status_code > 299:
                logger.error(err_msg)
                raise HCCIException(626278, url, err_msg)
            else:
                logger.info(err_msg)
            rsp_result = resp.get('result')
            rsp_data = resp
        except Exception as e:
            raise HCCIException(626101, str(e))
        return rsp_result, rsp_data

    def check_spdk_switch(self, node_list):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CHECK_SPDK_SWITCH
        data = {"serverList": node_list}

        try:
            res = self.rest_client.normal_request(url, 'post', data)
        except Exception as e:
            logger.error("Failed to deliver the request. Detail:%s" % str(e))
        result = ResponseParse(res)
        return result

    def add_policy_route(self, data):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.SET_POLICY_ROUTE
        try:
            res = self.rest_client.normal_request(url, 'post', data)
            result = ResponseParse(res)
            rsp_code, rsp_result, rsp_data = result.get_rsp_detail()
            if rsp_code != 0:
                err_msg = 'Failed to add policy route. Detail:[result:%s,' \
                          'code:%s]%s' % (rsp_code, rsp_result, rsp_data)
                logger.error(err_msg)
                raise Exception(err_msg)
        except Exception as e:
            logger.error("Failed to add policy route. Detail:%s" % str(e))
            raise HCCIException(626071, str(e))
        return rsp_result, rsp_data

    def query_policy_route(self, data):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.QUERY_POLICY_ROUTE
        try:
            res = self.rest_client.normal_request(url, 'post', data)
            result = ResponseParse(res)
            rsp_code, rsp_result, rsp_data = result.get_rsp_data()
            if rsp_code != 0:
                err_msg = 'Failed to query policy route. Detail:[result:%s,' \
                          'code:%s]%s' % (rsp_code, rsp_result, rsp_data)
                logger.error(err_msg)
                raise Exception(err_msg)
        except Exception as e:
            logger.error("Failed to query policy route. Detail:%s" % str(e))
            raise HCCIException(626071, str(e))
        return rsp_result, rsp_data

    def delete_policy_route(self, data):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.DEL_POLICY_ROUTE
        try:
            res = self.rest_client.normal_request(url, 'post', data)
            result = ResponseParse(res)
            rsp_code, rsp_result, _ = result.get_rsp_data()
            if rsp_code != 0:
                err_msg = 'Failed to query policy route. Detail:[result:%s,' \
                          'code:%s]%s' % (rsp_code, rsp_result, res.json())
                logger.error(err_msg)
                raise Exception(err_msg)
        except Exception as e:
            logger.error("Failed to query policy route. Detail:%s" % str(e))
            raise HCCIException(626071, str(e))
        return rsp_result

    def add_static_route(self, data):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.SET_STATIC_ROUTE
        try:
            res = self.rest_client.normal_request(url, 'post', data)
            result = ResponseParse(res)
            rsp_code, rsp_result, rsp_data = result.get_rsp_data()
            if rsp_code != 0:
                err_msg = 'Failed to add static route. Detail:[result:%s,' \
                          'code:%s]%s' % (rsp_code, rsp_result, rsp_data)
                logger.error(err_msg)
                raise Exception(err_msg)
        except Exception as e:
            logger.error("Failed to add static route. Detail:%s" % str(e))
            raise HCCIException(626071, str(e))
        return rsp_result, rsp_data

    def get_product(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + DeployConstant.PORT + DeployConstant.GET_PRODUCT
        try:
            logger.info("get product info url is: %s." % url)
            res = self.rest_client.normal_request(url, 'get').json()
            status = res.get('result').get('code')
            if status != 0:
                err_msg = "get product info failed.detail:%s" % str(res)
                logger.error(err_msg)
                raise Exception(err_msg)
            result = res.get('result')
            data = res.get("data")
        except Exception as e:
            logger.error('get product info fail.exception:%s' % e)
            raise Exception('get product info fail.exception:%s' % e)
        return result, data

    def get_cert(self, data):
        url = DeployConstant.HTTPS + self.float_ip + ":" + DeployConstant.PORT + DeployConstant.GET_DSWARE_CERT
        try:
            logger.info("get dsware cert url is: %s." % url)
            res = self.rest_client.normal_request(url, 'put', data)
            resp = res.json()
            status = resp.get('result')
            if status != 0:
                err_msg = "get dsware cert failed.detail:%s" % resp
                logger.error(err_msg)
                raise Exception(err_msg)
            result = resp.get('result')
            data = resp.get("data")
        except Exception as e:
            logger.error('get dsware cert failed.exception:%s' % e)
            raise Exception('get dsware cert fail.exception:%s' % e)
        return result, data

    def del_cert(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + DeployConstant.PORT + DeployConstant.DEL_DSWARE_CERT
        try:
            logger.info("Del dsware cert url is: %s." % url)
            res = self.rest_client.normal_request(url, 'delete')
            resp = res.json()
            status = resp.get('result').get('code')
            if status != 0:
                err_msg = "Del dsware cert failed.detail:%s" % resp
                logger.error(err_msg)
                raise Exception(err_msg)
            result = resp.get('result')
        except Exception as e:
            logger.error('Del dsware cert failed.exception:%s' % e)
            raise Exception('Del dsware cert failed.exception:%s' % e)
        return result

    def config_osd_node_bmc_account_info(self, data):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CONFIG_BMC_PWD
        try:
            res = self.rest_client.normal_request(url, 'put', data)
            resp = res.json()
            result, data = resp.get('result'), resp.get('data')
            code = result.get('code')
            if code != 0:
                err_msg = 'Failed to config the bmc information, details: {}'.format(data)
                logger.error(err_msg)
                raise HCCIException(626333, str(resp))
        except Exception as e:
            raise HCCIException(626333, str(e))
        return data

    def create_encrypted_account(self, username, password, kms_type):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CREATE_ACCOUNT_WITH_ENCRYPT
        ac_data = {"id": '0',
                   "encryptOption": 1,
                   "kmsType": kms_type}
        res = []
        try:
            retry = 0
            created_account = False
            task_data = dict()
            # 三次重试
            while retry < 3:
                res = self.rest_client.normal_request(url, 'put', ac_data, keepsession=True)
                resp = res.json()
                status_code = resp.get('result')
                task_data['status_code'] = status_code
                if status_code == 0:
                    created_account = True
                    task_data['data'] = resp.get('data')
                    logger.info('Create encrypted account with REST successful')
                    break
                task_data['data'] = resp.get('data')
                task_data['error_code'] = resp.get('data').get('errorCode')
                task_data['error_msg'] = resp.get('data').get('errorMsg')
                self.check_session_and_retry_login(username, password)
                retry += 1
                logger.error('Try to create account with encrypt option in %s time. '
                             'Details:[code:%s]%s' % (retry, task_data['error_code'], task_data['error_msg']))
            if not created_account:
                err_msg = 'Failed to create account with encrypt option, ' \
                          'details:[code:%s]%s' % (task_data['error_code'], task_data['error_msg'])
                logger.error(err_msg)
                raise Exception(err_msg)
        except JSONDecodeError:
            logger.error('REST interface returned value is not json type')
            raise HCCIException(626371, "Response is not json type, details: {}".format(str(res)))
        except Exception as e:
            logger.error('Failed to create account with encrypt option, details:%s' % str(e))
            raise HCCIException(626372, str(e))
        return task_data

    def check_session_and_retry_login(self, username, password):
        """
        若会话过期，重新登录
        :param username:
        :param password:
        :return:
        """
        result, data = self.rest_client.get_session()
        logger.info('Current session(%s, %s)' % (result, data))
        if result['code'] != 0:
            logger.info('Try login again.')
            self.login(username, password, keep_session=True)
        for resp in data:
            if resp['status'] != '1':
                logger.info('Session timeout. Try login again.')
                self.login(username, password, keep_session=True)

    def config_external_kms_info(self, kms_info):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CONFIG_EXTERNAL_KMS_INFO
        res = []
        try:
            res = self.rest_client.normal_request(url, 'post', kms_info)
            resp = res.json()
            status_code, error_code, error_des = resp.get('result'), resp.get('errorCode'), resp.get('description')
            error_suggestion = resp.get('suggestion')
            if status_code != 0:
                err_msg = 'Failed to config external kms info. Detail:[result:%s,' \
                          'code:%s]%s. Suggestion:%s' % (status_code, error_code, error_des, error_suggestion)
                logger.error(err_msg)
                raise Exception(err_msg)
        except JSONDecodeError:
            logger.error('REST interface returned value is not json type')
            raise HCCIException(626371, "Response is not json type, details: {}".format(str(res)))
        except Exception as e:
            logger.error('Failed to config external kms info. Detail:%s' % str(e))
            raise HCCIException(626357, str(e))
        return status_code, error_code, error_des

    def query_external_kms_info(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.QUERY_EXTERNAL_KMS_INFO
        res = []
        try:
            res = self.rest_client.normal_request(url, 'get')
            resp = res.json()
            result, data_list = resp.get('result'), resp.get('list')
            if result != 0:
                err_msg = "Get external kms info failed. Detail:%s" % resp
                logger.error(err_msg)
                raise Exception(err_msg)
        except JSONDecodeError:
            logger.error('REST interface returned value is not json type')
            raise HCCIException(626371, "Response is not json type, details: {}".format(str(res)))
        except Exception as e:
            logger.error("Failed to get external kms info. Detail:%s" % str(e))
            raise HCCIException(626362, str(e))
        return result, data_list

    def delete_external_kms_info(self, kms_id):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.DELETE_EXTERNAL_KMS_INFO\
              + '/' + kms_id
        res = []
        try:
            res = self.rest_client.normal_request(url, 'delete')
            result = res.json()
            status = result.get('result')
            if status != 0:
                err_msg = "delete external kms failed.detail:%s" % result
                logger.error(err_msg)
                raise Exception(err_msg)
        except JSONDecodeError:
            logger.error('REST interface returned value is not json type')
            raise HCCIException(626371, "Response is not json type, details: {}".format(str(res)))
        except Exception as e:
            logger.error('Failed to delete external kms info. Detail:%s' % str(e))
            raise HCCIException(626361, str(e))
        return result

    def import_certificate(self, username, password, file_info):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.IMPORT_CERTIFICAT \
              % self.sys_esn + "?certificateType=" + file_info.get('cert_type') + "&fileName=" \
              + file_info.get('file_name') + "&fileType=" + file_info.get('file_type')
        try:
            file_path = file_info.get('file_path')
            res = self.rest_client.upload_cert_request(url, 'post', file_path, username, password)
            status_code = res.get('status_code')
            content = res.get('content')
            if content:
                error_code, error_des = content.get('result').get('code'), content.get('result').get('description')
                error_suggestion = content.get('result').get('suggestion')
                if error_code:
                    err_msg = "failed to import certificate. Detail:[result:%s, " \
                                "code:%s]%s. Suggestion:%s" % (status_code, error_code, error_des, error_suggestion)
                    logger.error(err_msg)
                    raise Exception(err_msg)
        except Exception as e:
            logger.error('Failed to import certificate. Detail:%s' % str(e))
            raise HCCIException(626358, file_info.get('file_path'), str(e))
        return status_code

    def activat_certificate(self, cert_type):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.ACTIVATE_CERTIFICAT % self.sys_esn
        data = {'CERTIFICATE_TYPE': cert_type}
        res = []
        try:
            res = self.rest_client.normal_request(url, 'put', data)
            resp = res.json()
            result = resp.get('result')
            status_code = result.get('code')
            if status_code != 0:
                err_msg = "failed to activate certificate.detail:%s" % resp
                logger.error(err_msg)
                raise Exception(err_msg)
        except JSONDecodeError:
            logger.error('REST interface returned value is not json type')
            raise HCCIException(626371, "Response is not json type, details: {}".format(str(res)))
        except Exception as e:
            logger.error('Failed to activate certificate. Detail:%s' % str(e))
            raise HCCIException(626356, str(e))
        return result, status_code

    def test_external_kms_connectivity(self, kms_info, timeout=None):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.TEST_KMS_CONNECTIVITY
        res = self.rest_client.normal_request(url, 'post', kms_info, timeout=timeout)
        resp = res.json()
        status_code, error_code, error_des = resp.get('result'), resp.get('errorCode'), resp.get('description')
        return status_code, error_code, error_des

    def get_dsware_global_params(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CHECK_DSW_GLOBAL
        res = self.rest_client.normal_request(url, 'get')
        resp = res.json()
        result, parameter = resp.get('result'), resp.get('parameter')
        if result != 0:
            err_msg = 'Failed to query DSW_GLOBAL parameters, details: {}'.format(resp)
            logger.error(err_msg)
            raise HCCIException(626304, str(resp))
        return parameter

    def modify_dsware_global_params(self, param_name, value='0'):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.MODIFY_DSW_GLOBAL
        body = {
            'parameter': [{'paraName': param_name, 'value': value}],
            'opType': 'modify'
        }
        res = self.rest_client.normal_request(url, 'post', data=body)
        resp = res.json()
        result, detail = resp.get('result'), resp.get('detail')
        if result != 0:
            err_msg = 'Failed to modify DSW_GLOBAL parameter: {}, details: {}'.format(param_name, resp)
            logger.error(err_msg)
            raise HCCIException(626304, str(resp))
        return detail

    def get_cluster_network_info(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.NET_SERVICE
        try:
            res = self.rest_client.normal_request(url, 'post', data={})
        except Exception as e:
            raise HCCIException(626304, e)
        result = ResponseParse(res).get_query_data()
        status, data = result.get('result').get('code'), result.get('data')
        if status != 0:
            logger.error('Failed to query the cluster network')
            raise HCCIException(626304, result.get('result'))
        return data

class FusionStorageOperate(DeployOperate):
    def __init__(self, float_ip):
        self.float_ip = float_ip
        self.port = DeployConstant.PORT
        self.rest_client = RestClient(self.float_ip)
        self.sys_esn = None


class RedfishOperate(object):
    def __init__(self, ip, username, password, port='443'):
        self.https = 'https://'
        self.ip = ip
        self.port = port
        self.client = RestClient(self.ip, port)
        self.login(username, password)

    def login(self, username, password):
        try:
            res = self.client.redfish_login(username, password)
            if res.status_code != 200 and res.status_code != 201:
                if res.json().get("error"):
                    error_msg = "redfish login %s failed, %s" % (self.ip, res)
                    logger.error(error_msg)
                    raise Exception(error_msg)
        except Exception as e:
            logger.error("redfish login %s failed, exc: %s" % (self.ip, e))
            raise HCCIException(627618, str(e))

    def get_iommu(self):
        system_uri = "/redfish/v1/Systems/"
        url = DeployConstant.HTTPS + self.ip + ":" + self.port + system_uri
        try:
            res = self.client.normal_request(url, 'get')
            resp = res.json()
            logger.info("get %s systems res %s" % (self.ip, resp))
            members = resp.get('Members')
            system_url = members[0].get("@odata.id")
        except Exception as e:
            err_msg = "Get %s from %s failed, err:%s" % (url, self.ip, str(e))
            logger.error(err_msg)
            raise HCCIException(627618, str(e))

        resource_uri = system_url + "/Bios"
        url = DeployConstant.HTTPS + self.ip + ":" + self.port + resource_uri
        try:
            res = self.client.normal_request(url, 'get')
            resp = res.json()
            logger.info("get %s io mmu res %s" % (self.ip, resp))
            iommu_status = resp.get('Attributes').get('EnableSMMU')
        except Exception as e:
            err_msg = "Get %s from %s failed, err:%s" % (url, self.ip, str(e))
            logger.error(err_msg)
            raise HCCIException(627618, str(e))
        return iommu_status

    def get_system_arch(self):
        system_uri = "/redfish/v1/Systems/"
        url = DeployConstant.HTTPS + self.ip + ":" + self.port + system_uri
        try:
            res = self.client.normal_request(url, 'get')
            resp = res.json()
            logger.info("get %s systems res %s" % (self.ip, resp))
            members = resp.get('Members')
            system_url = members[0].get("@odata.id")
        except Exception as e:
            err_msg = "Get %s from %s failed, err:%s" % (url, self.ip, str(e))
            logger.error(err_msg)
            raise HCCIException(627618, str(e))

        processors_uri = system_url + "/Processors"
        url = DeployConstant.HTTPS + self.ip + ":" + self.port + processors_uri
        try:
            res = self.client.normal_request(url, 'get')
            resp = res.json()
            logger.info("get %s processors res %s" % (self.ip, resp))
            members = resp.get('Members')
            processors_url = members[0].get("@odata.id")
        except Exception as e:
            err_msg = "Get %s from %s failed, err:%s" % (url, self.ip, str(e))
            logger.error(err_msg)
            raise HCCIException(627618, str(e))

        resource_uri = processors_url
        url = DeployConstant.HTTPS + self.ip + ":" + self.port + resource_uri
        try:
            res = self.client.normal_request(url, 'get')
            resp = res.json()
            logger.info("get %s system arch res %s" % (self.ip, resp))
            process_arch = resp.get('ProcessorArchitecture')
        except Exception as e:
            err_msg = "Get %s from %s failed, err:%s" % (url, self.ip, str(e))
            logger.error(err_msg)
            raise HCCIException(627618, str(e))
        return process_arch.upper()
