#!/usr/bin/python
# -*- coding: UTF-8 -*-
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
import time
import traceback
from collections import namedtuple
from json.decoder import JSONDecodeError

import utils.common.log as logger
from utils.common.exception import HCCIException

from plugins.DistributedStorage.utils.client.rest_client import RestClient
from plugins.DistributedStorage.utils.common.deploy_constant import DeployConstant
from plugins.DistributedStorage.utils.client.response_parse import ResponseParse


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)) from 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)) from 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)) from 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)) from e
        result = ResponseParse(res)
        return result

    def get_upgrade_status(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.GET_UPGRADE_STATUS
        try:
            res = self.rest_client.normal_request(url, 'get')
        except Exception as err:
            logger.error(traceback.format_exc())
            raise err
        result = ResponseParse(res)
        _, _, ret_data = result.get_rsp_data()
        return res.json(), ret_data

    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)) from 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)) from 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)) from 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)) from 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)) from 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', **kwargs):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.NET_PLATFORM
        net_info = {'bond_mode': kwargs.get("bond_mode", ""),
                    'ip_list': notwork_list,
                    'network_type': net_type,
                    'transfer_protocol': kwargs.get("protocal", "TCP"),
                    'scenario': scenario}
        try:
            res = self.rest_client.normal_request(url, 'put', net_info)
        except Exception as e:
            raise HCCIException(626071, str(e)) from e
        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')
        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)) from 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')
        except Exception as e:
            raise HCCIException(626071, str(e)) from e
        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)
        return rsp_result, rsp_data

    def config_net_validity(self, network_type, node_list):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.NET_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 + DeployConstant.NET_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}
        try:
            res = self.rest_client.normal_request(url, 'post', net_info)
        except Exception as e:
            raise HCCIException(626072, str(e)) from e
        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')
        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)) from e
        result = ResponseParse(res)
        return result

    def delete_manage_cluster(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.DELETE_MANAGE_CLUSTER
        cluster_info = None
        try:
            res = self.rest_client.normal_request(url, 'post', cluster_info)
        except Exception as e:
            raise HCCIException(626072, str(e)) from e
        result = res.json()
        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')
        except Exception as e:
            raise HCCIException(626073, str(e)) from e
        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)
        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')
        except Exception as e:
            raise HCCIException(626073, str(e)) from e
        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
        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)
        except Exception as e:
            raise HCCIException(626073, str(e)) from e
        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)
        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)

        logger.info("disable ssd compression and deduplication")
        ssd_compression_parameter_list = [{'paraName': 'ssd_compression_function_switch', 'value': '0'}]
        self.set_globalparam(ssd_compression_parameter_list)
        ssd_deduplication_parameter_list = [{'paraName': 'ssd_deduplication_function_switch', 'value': '0'}]
        self.set_globalparam(ssd_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)
        except Exception as e:
            raise HCCIException(626074, str(e)) from e
        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)
        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)) from 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)) from 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')
        except Exception as e:
            raise HCCIException(626076, str(e)) from e
        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)
        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')
        except Exception as e:
            raise HCCIException(626077, str(e)) from e
        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)
        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')
        except Exception as e:
            raise HCCIException(626078, str(e)) from e
        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)
        return reslut

    def query_disk_pool(self, pool_id):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.QUERY_DISK_POOL.format(pool_id)
        try:
            res = self.rest_client.normal_request(url, 'get')
        except Exception as err:
            raise HCCIException(626078, str(err)) from err
        result = ResponseParse(res)
        rsp = result.get_query_data()
        logger.info(rsp)
        if rsp.get("result") != 0:
            err_msg = 'Failed to query diskPools. Detail:{}'.format(rsp)
            logger.error(err_msg)
            raise HCCIException(626078, err_msg)
        return rsp

    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')
        except Exception as e:
            raise HCCIException(626078, str(e)) from e
        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
        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')
        except Exception as e:
            raise HCCIException(626076, str(e)) from e
        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)
        return result

    def create_client(self, node_ip_list):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.CREATE_CLIENT
        server_list = [{"nodeMgrIp": x, "nodeType": 0} 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)) from 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
        server_list = [{"nodeMgrIp": x, "nodeType": 0}
                       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)) from e
        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
        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)) from 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)) from 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)
        except Exception as e:
            raise HCCIException(626099, str(e)) from e
        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')
        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)) from 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)
        except Exception as e:
            raise HCCIException(626100, str(e)) from e
        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')
        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)) from 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)
        except Exception as e:
            raise HCCIException(626101, str(e)) from e
        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')
        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
        data = {"servers": [{"management_internal_ip": manage_ip}]}
        try:
            res = self.rest_client.normal_request(url, 'post', data)
        except Exception as e:
            raise HCCIException(626101, str(e)) from e
        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')
        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
        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)
        try:
            res = self.rest_client.normal_request(url, 'post', data)
        except Exception as e:
            raise HCCIException(626071, str(e)) from e
        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)
        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
        data = {"ips": [manage_ip],
                "switch": 0}
        try:
            res = self.rest_client.normal_request(url, 'post', data)
        except Exception as e:
            raise HCCIException(626101, str(e)) from e
        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
        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
        data = {"iscsiIp": storage_ip,
                "iscsiPort": port,
                "nodeMgrIps": [manage_ip]}
        try:
            res = self.rest_client.normal_request(url, 'post', data)
        except Exception as e:
            raise HCCIException(626101, str(e)) from e
        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
        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)
        except Exception as e:
            logger.error("Failed to add policy route. Detail:%s" % str(e))
            raise HCCIException(626071, str(e)) from e
        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)
        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)
        except Exception as e:
            logger.error("Failed to query policy route. Detail:%s" % str(e))
            raise HCCIException(626071, str(e)) from e
        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 HCCIException(626071, err_msg)
        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)
        except Exception as e:
            logger.error("Failed to query policy route. Detail:%s" % str(e))
            raise HCCIException(626071, str(e)) from e
        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 HCCIException(626071, err_msg)
        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)
        except Exception as e:
            logger.error("Failed to add static route. Detail:%s" % str(e))
            raise HCCIException(626071, str(e)) from e
        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 HCCIException(626071, err_msg)
        return rsp_result, rsp_data

    def get_product(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + DeployConstant.PORT + DeployConstant.GET_PRODUCT
        logger.info("get product info url is: %s." % url)
        try:
            res = self.rest_client.normal_request(url, 'get').json()
        except Exception as e:
            logger.error('get product info fail.exception:%s' % e)
            raise Exception('get product info fail.exception:%s' % e) from e
        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")
        return result, data

    def get_cert(self, passwd, output_type=None):
        url = DeployConstant.HTTPS + self.float_ip + ":" + DeployConstant.PORT + DeployConstant.GET_DSWARE_CERT
        data = {"password": passwd, "output_type": output_type} if output_type else {"password": passwd}
        logger.info("get dsware cert url is: %s." % url)
        try:
            res = self.rest_client.normal_request(url, 'put', data)
        except Exception as e:
            logger.error('get dsware cert failed.exception:%s' % e)
            raise Exception('get dsware cert fail.exception:%s' % e) from e
        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")
        return result, data

    def del_cert(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + DeployConstant.PORT + DeployConstant.DEL_DSWARE_CERT
        logger.info("Del dsware cert url is: %s." % url)
        try:
            res = self.rest_client.normal_request(url, 'delete')
        except Exception as e:
            logger.error('Del dsware cert failed.exception:%s' % e)
            raise Exception('Del dsware cert failed.exception:%s' % e) from e
        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')
        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)
        except Exception as e:
            raise HCCIException(626333, str(e)) from e
        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))
        return data

    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) from 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

    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}
        retry = 0
        created_account = False
        task_data = dict()
        # 三次重试
        while retry < 3:
            try:
                res = self.rest_client.normal_request(url, 'put', ac_data, keepsession=True)
            except Exception as e:
                logger.error('Failed to create account with encrypt option, details:%s' % str(e))
                raise HCCIException(626372, str(e)) from e
            try:
                resp = res.json()
            except JSONDecodeError as e:
                logger.error('REST interface returned value is not json type, details:{}'.format(e))
                raise HCCIException(626371, str(e)) from e
            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')
            time.sleep(300)
            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.get('error_code'), task_data.get('error_msg')))
        if not created_account:
            err_msg = 'Failed to create account with encrypt option, ' \
                      'details:[code:%s]%s' % (task_data.get('error_code'), task_data.get('error_msg'))
            logger.error(err_msg)
            raise Exception(err_msg)
        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
        try:
            res = self.rest_client.normal_request(url, 'post', kms_info)
        except Exception as e:
            logger.error('Failed to config external kms info. Detail:%s' % str(e))
            raise HCCIException(626357, str(e)) from e
        try:
            resp = res.json()
        except JSONDecodeError as e:
            logger.error('REST interface returned value is not json type')
            raise HCCIException(626371, "Response is not json type, details: {}".format(str(res))) from e
        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 HCCIException(626357, err_msg)
        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
        try:
            res = self.rest_client.normal_request(url, 'get')
        except Exception as e:
            logger.error("Failed to get external kms info. Detail:%s" % str(e))
            raise HCCIException(626362, str(e)) from e
        try:
            resp = res.json()
        except JSONDecodeError as e:
            logger.error('REST interface returned value is not json type')
            raise HCCIException(626371, "Response is not json type, details: {}".format(str(res))) from e
        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 HCCIException(626362, err_msg)
        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
        try:
            res = self.rest_client.normal_request(url, 'delete')
        except Exception as e:
            logger.error('Failed to delete external kms info. Detail:%s' % str(e))
            raise HCCIException(626361, str(e)) from e
        try:
            result = res.json()
        except JSONDecodeError as e:
            logger.error('REST interface returned value is not json type')
            raise HCCIException(626371, "Response is not json type, details: {}".format(str(res))) from e
        status = result.get('result')
        if status != 0:
            err_msg = "delete external kms failed.detail:%s" % result
            logger.error(err_msg)
            raise HCCIException(626361, err_msg)
        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')
        file_path = file_info.get('file_path')
        date_tuple = namedtuple('date_tuple', ['url', 'method', 'file_path', 'username', 'password'])
        date_info = date_tuple(url, 'post', file_path, username, password)
        try:
            res = self.rest_client.upload_cert_request(date_info)
        except Exception as e:
            logger.error('Failed to import certificate. Detail:%s' % str(e))
            raise HCCIException(626358, file_info.get('file_path'), str(e)) from e
        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 HCCIException(626358, err_msg)
        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}
        try:
            res = self.rest_client.normal_request(url, 'put', data)
        except Exception as e:
            logger.error('Failed to activate certificate. Detail:%s' % str(e))
            raise HCCIException(626390, str(e), traceback.format_exc()) from e
        try:
            resp = res.json()
        except JSONDecodeError as e:
            logger.error('REST interface returned value is not json type')
            raise HCCIException(626371, "Response is not json type, details: {}".format(str(res))) from e
        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 HCCIException(626390, data, resp)
        return result, status_code

    def export_csr(self, csr_type=3, algorithm=1):
        values = (self.sys_esn, csr_type, algorithm)
        url = DeployConstant.HTTPS + self.float_ip + ':' + self.port + DeployConstant.EXPORT_CSR % values
        result = self.rest_client.normal_request(url, 'get')
        resp = result.json()
        if not resp or resp.get('result').get('code') != 0:
            logger.error('Failed to export the .csr file, response:{}'.format(resp))
            raise HCCIException(626278, url, resp)
        output = resp.get('data')
        if not output.get("CERTIFICATE_CSR_NAME") or not output.get("CERTIFICATE_EXPORT_PATH"):
            logger.error('Failed to generate the .csr file, response:{}'.format(resp))
            raise HCCIException(626278, url, resp)
        return output

    def download_csr(self, csr_path, csr_type=3):
        values = (self.sys_esn, csr_path, csr_type)
        url = DeployConstant.HTTPS + self.float_ip + ':' + self.port + DeployConstant.DOWNLOAD_CSR % values
        try:
            result = self.rest_client.download_file_request(url, 'get')
        except Exception as e:
            err_msg = 'Download csr error: {}, details: {}'.format(e, traceback.format_exc())
            logger.error(err_msg)
            raise e
        return result.content

    def import_csr(self, csr_file_path, dm_password, cert_name="dsware_api"):
        values = (self.sys_esn, cert_name)
        url = DeployConstant.HTTPS + self.float_ip + ':' + self.port + DeployConstant.CSR_UPLOAD % values
        date_tuple = namedtuple('date_tuple', ['url', 'method', 'file_path', 'username', 'password'])
        date_info = date_tuple(url, 'post', csr_file_path, DeployConstant.DM_LOGIN_USER, dm_password)
        try:
            res = self.rest_client.upload_cert_request(date_info)
        except Exception as err:
            logger.error('Failed to import csr. Detail:{}'.format(err))
            raise HCCIException(626278, url, err) from err
        logger.info("response:{}".format(res))
        status_code = res.get('status_code')
        if status_code != 200:
            raise Exception(res)

    def issue_cert(self, data: dict):
        url = DeployConstant.HTTPS + self.float_ip + ':' + self.port + DeployConstant.ISSUE_CERT % self.sys_esn
        try:
            res = self.rest_client.normal_request(url, "post", data)
        except Exception as err:
            logger.error("Issue Cert Error:{}, details:{}".format(err, traceback.format_exc()))
            raise HCCIException(626278, url, err) from err
        result = ResponseParse(res)
        res_data = result.get_query_data()
        return res_data

    def export_cert(self, cert_name):
        values = (self.sys_esn, cert_name)
        url = DeployConstant.HTTPS + self.float_ip + ':' + self.port + DeployConstant.EXPORT_CERT % values
        try:
            res = self.rest_client.normal_request(url, "get")
        except Exception as err:
            logger.error("Export Cert Error:{}, details:{}".format(err, traceback.format_exc()))
            raise HCCIException(626278, url, err) from err
        result = ResponseParse(res)
        res_data = result.get_query_data()
        return res_data

    def download_cert(self, cert_path, cert_name):
        values = (self.sys_esn, cert_path, cert_name)
        url = DeployConstant.HTTPS + self.float_ip + ':' + self.port + DeployConstant.SAVE_CERT % values
        try:
            res = self.rest_client.download_file_request(url, "get")
        except Exception as err:
            logger.error("Download Cert Error:{}, details:{}".format(err, traceback.format_exc()))
            raise HCCIException(626278, url, err) from err
        return res.content

    def export_ca(self, ca_name):
        values = (self.sys_esn, ca_name)
        url = DeployConstant.HTTPS + self.float_ip + ':' + self.port + DeployConstant.EXPORT_CA % values
        try:
            res = self.rest_client.normal_request(url, "get")
        except Exception as err:
            logger.error("Export CA Error:{}, details:{}".format(err, traceback.format_exc()))
            raise HCCIException(626278, url, err) from err
        result = ResponseParse(res)
        res_data = result.get_query_data()
        return res_data

    def download_ca(self, ca_path, ca_name):
        values = (self.sys_esn, ca_path, ca_name)
        url = DeployConstant.HTTPS + self.float_ip + ':' + self.port + DeployConstant.SAVE_CA % values
        try:
            res = self.rest_client.download_file_request(url, "get")
        except Exception as err:
            logger.error("Download Ca Error:{}, details:{}".format(err, traceback.format_exc()))
            raise HCCIException(626278, url, err) from err
        return res.content

    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 query_os_sandbox(self):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.SANDBOX_FOR_NODES
        try:
            res = self.rest_client.normal_request(url, 'get')
        except Exception as e:
            raise HCCIException(626387, str(e)) from e
        try:
            resp = res.json()
        except JSONDecodeError as e:
            logger.error('REST interface returned value is not json type')
            raise HCCIException(626371, "Response is not json type, details: {}".format(str(res))) from e
        result, data = resp.get('result'), resp.get('data')
        if result.get('code') != 0:
            err_msg = 'Failed to query sandbox configuration info, details: {}'.format(resp)
            logger.error(err_msg)
            raise Exception(err_msg)
        return data

    def enable_os_sandbox(self, node_ips):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.SANDBOX_FOR_NODES
        body = {'start': {'node_ips': node_ips}}
        try:
            res = self.rest_client.normal_request(url, 'post', body)
        except Exception as e:
            raise HCCIException(626387, str(e)) from e
        try:
            resp = res.json()
        except JSONDecodeError as e:
            logger.error('REST interface returned value is not json type')
            raise HCCIException(626371, "Response is not json type, details: {}".format(str(res))) from e
        result, data = resp.get('result'), resp.get('data')
        if result.get('code') != 0:
            err_msg = 'Failed to enable sandbox configuration info, details: {}'.format(resp)
            logger.error(err_msg)
            raise HCCIException(626387, err_msg)
        return data

    def disable_os_sandbox(self, node_info):
        resp = self.disable_sandbox_handle(node_info)
        result, data = resp.get('result'), resp.get('data')
        if result.get('code') != 0:
            err_msg = 'Failed to disable sandbox configuration info, details: {}'.format(resp)
            logger.error(err_msg)
            raise Exception(err_msg)
        return data

    def disable_sandbox_handle(self, node_info):
        url = DeployConstant.HTTPS + self.float_ip + ":" + self.port + DeployConstant.SANDBOX_FOR_NODES
        body = {'stop': node_info}
        try:
            res = self.rest_client.normal_request(url, 'post', body)
        except Exception as e:
            raise HCCIException(626387, str(e)) from e
        try:
            resp = res.json()
        except JSONDecodeError as e:
            logger.error('REST interface returned value is not json type')
            raise HCCIException(626371, "Response is not json type, details: {}".format(str(res))) from e
        return resp


class FusionStorageOperate(DeployOperate):
    def __init__(self, fs_info=None, float_ip=None):
        super(FusionStorageOperate, self).__init__(fs_info, 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)
        except Exception as e:
            logger.error("redfish login %s failed, exc: %s" % (self.ip, e))
            raise HCCIException(627618, str(e)) from e
        if res.status_code != 200 and res.status_code != 201 and res.json().get("error"):
            error_msg = "redfish login %s failed, %s" % (self.ip, res)
            logger.error(error_msg)
            raise Exception(error_msg)

    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')
        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)) from e
        resp = res.json()
        logger.info("get %s systems res %s" % (self.ip, resp))
        members = resp.get('Members')
        system_url = members[0].get("@odata.id")
        resource_uri = "{}/{}".format(system_url, "Bios")
        url = DeployConstant.HTTPS + self.ip + ":" + self.port + resource_uri
        try:
            res = self.client.normal_request(url, 'get')
        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)) from e
        resp = res.json()
        logger.info("get %s io mmu res %s" % (self.ip, resp))
        iommu_status = resp.get('Attributes').get('EnableSMMU')
        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')
        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)) from e
        resp = res.json()
        logger.info("get %s systems res %s" % (self.ip, resp))
        members = resp.get('Members')
        system_url = members[0].get("@odata.id")

        processors_uri = "{}/{}".format(system_url, "Processors")
        url = DeployConstant.HTTPS + self.ip + ":" + self.port + processors_uri
        try:
            res = self.client.normal_request(url, 'get')
        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)) from e
        resp = res.json()
        logger.info("get %s processors res %s" % (self.ip, resp))
        members = resp.get('Members')
        processors_url = members[0].get("@odata.id")
        resource_uri = processors_url
        url = DeployConstant.HTTPS + self.ip + ":" + self.port + resource_uri
        try:
            res = self.client.normal_request(url, 'get')
        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)) from e
        resp = res.json()
        logger.info("get %s system arch res %s" % (self.ip, resp))
        process_arch = resp.get('ProcessorArchitecture')
        return process_arch.upper()


class SandBoxHandle:

    @classmethod
    def is_enabled_on_osd_nodes(cls, operate: DeployOperate, target_pool_nodes_ip_lst):
        is_enabled = False
        rsp_obj = operate.query_cluster_servers()
        rsp_code, rsp_result, rsp_data = rsp_obj.get_rsp_data()
        if rsp_code != 0 or rsp_result.get('code') != 0:
            err_msg = "Failed to query cluster nodes info, Error:{}".format(rsp_result)
            logger.error(err_msg)
            raise Exception(err_msg)
        nodes_status = {}
        for server in rsp_data:
            node_role = server.get('role')
            node_ip = server.get('management_ip')
            if 'storage' not in node_role or node_ip not in target_pool_nodes_ip_lst:
                continue
            sandbox_status = server.get('sandbox_status')
            nodes_status[node_ip] = sandbox_status
            logger.info("Node[{}] sandbox status:{}".format(node_ip, sandbox_status))
            if sandbox_status == 0:
                is_enabled = True
                logger.info('Node [%s] sandbox is enable.' % node_ip)
        if len(set(nodes_status.values())) != 1:
            err_msg = "The sandbox status of the nodes is different:{}".format(nodes_status)
            logger.error(err_msg)
            raise Exception(err_msg)
        logger.info("Sandbox status on nodes:{}".format(is_enabled))
        return is_enabled

    @classmethod
    def before_check_disable_osd_sandbox(cls, operate: DeployOperate, target_pool_nodes_ip_lst,
                                         original_az_osd_root_pwd, reuse_fsm_admin_passwd):
        logger.info('Disable OS sandbox for nodes')
        data = operate.query_os_sandbox()
        if data.get('support_disable_sandbox') != 0:
            err_msg = 'The cluster OS security sandbox is not supported to be disabled.'
            logger.error(err_msg)
            raise Exception(err_msg)
        disable_nodes = {'node_ips': target_pool_nodes_ip_lst,
                         'root_password': original_az_osd_root_pwd,
                         'admin_password': reuse_fsm_admin_passwd}
        data = operate.disable_os_sandbox(disable_nodes)
        failed_nodes_list = []
        for node in data:
            if node.get('code') != 0:
                failed_nodes_list.append(node)
        if failed_nodes_list:
            err_msg = 'Failed disable sandbox nodes list: %s' % failed_nodes_list
            logger.error(err_msg)
            raise Exception('Disable sandbox fail')
        logger.info('Disable OS sandbox for nodes finish')

    @classmethod
    def after_check_enable_osd_sandbox(cls, operate: DeployOperate, target_pool_nodes_ip_lst):
        logger.info('Enable OS sandbox for nodes')
        data = operate.enable_os_sandbox(target_pool_nodes_ip_lst)
        failed_nodes_list = []
        for node in data:
            if node.get('code') != 0:
                failed_nodes_list.append(node)
        if failed_nodes_list:
            err_msg = 'Failed enable sandbox nodes list: %s' % failed_nodes_list
            logger.error(err_msg)
            raise Exception(err_msg)
        logger.info('Enable OS sandbox for nodes success')
