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

import utils.common.log as logger
from utils.common.ssh_util import Ssh
from utils.common.fic_base import TestCase
from utils.client.FSPAuthClient import FSPAuthClient
from utils.common.message import Message
from utils.common.exception import FCDException
from utils.common.OpenStackNodeManager import OpenStackNodeManager
from utils.PasswordManager.PasswordManager import FSPasswordManager
from utils.Driver.CloudDC.OpenStack.get_host_info import GetHostInfo
from utils.Driver.CloudDC.OpenStack.config_cascading_kvm import ConfinCascadingKvm

from platforms.project.ProjectUtils import get_project_conditions
from platforms.project.ProjectUtils import get_project_condition_boolean

from plugins.DistributedStorage.scripts.logic.DeployOperate import DeployOperate
from plugins.DistributedStorage.scripts.logic.InstallOperate import InstallOperate
from plugins.DistributedStorage.scripts.utils.common.DeployConstant import DeployConstant


class ConfigResourcePool(TestCase):
    def __init__(self, project_id, pod_id, fs_args, condition=None, metadata=None, **kwargs):
        super(ConfigResourcePool, self).__init__(project_id, pod_id)
        self.float_ip = fs_args.get('float_ip')
        self.vbs_list = fs_args.get('vbs_list')
        self.update_pwd = fs_args.get('dm_update_pwd')
        self.az_id = fs_args.get('az_id')
        self.opr = DeployOperate(fs_args)
        self.condition = condition
        self.metadata = metadata
        self.more_args = kwargs
        self.bms_condition = get_project_condition_boolean(self.project_id, 'TenantStorFB80&BMS')
        self.install_opr = InstallOperate(self.project_id, self.pod_id, fs_args)

    def procedure(self):
        """
        对接原则：
        1. 部署工程、扩AZ新建存储集群、扩AZ复用、扩计算AZ复用已有存储场景，都会新增一个cinder-kvm00X服务,直接对接。通过LLD表填的az_id和
           enabled_backend查到已存在cinder-kvm00X，说明LLD表填写错误或有历史残留，工步抛错：
              （1） 一个后端内的多个存储池，存储池id通过逗号隔开，对接到一个 后端存储配置名称 内
              （2） 多个后端，cps---配置---资源池管理---配置存储集群---后端存储配置 对应多个配置栏
        2. 新增业务存储--新增存储池场景，往已有AZ内扩存储池，不会新增cinder-kvm00X。通过LLD表填的az_id和enabled_backend应该查到已有的
           cinder-kvm00X，如果未查到，说明LLD表填写错误，工步抛错。对接通过patch方法更新：
             （1） 如果cinder-kvm00X内存在LLD表填写的业务存储后端存储名，则将已有的存储池id和新扩的存储id通过逗号连接，update到cps已有
                  的后端存储配置名称
             （2） 如果cinder-kvm00X内未查到LLD表填写的业务存储后端存储名，则cps---配置---资源池管理---配置存储集群---后端存储配置 新
                  增一栏，对接当前待对接的后端存储
        """
        try:
            logger.info('Start to query section list and enabled_backend name')
            pool_name_id_dict = self.get_storage_pool_name_id_map()
            section_list, multi_backend = self.get_multiple_backend_section(pool_name_id_dict)
            enabled_backend = multi_backend[0]

            logger.info('Start to upload certificates and get private key')
            webui_client = FSPAuthClient.get_cps_web_client(self.db, self.project_id, self.pod_id)
            private_key_psw = self.install_opr.upload_cert_and_get_private_key(webui_client)

            logger.info("Start to check multiple enabled backend")
            obj = ConfinCascadingKvm(webui_client)
            resource_pool_data = obj.get_kvm_resource_pool()
            add_new_pool, cinder_driver_info = self.multi_backend_name_config_check(multi_backend, resource_pool_data)

            logger.info("Start to get the cluster name, id and ip of compute nodes or control nodes")
            old_compute_ip_list = list()
            old_compute_id_list = list()
            cluster_name = ''
            if add_new_pool:
                logger.info('This is the increase storage pool scenario')
                cps_hosts = GetHostInfo(webui_client).get_hosts_info()
                all_host_ids = {host["omip"]: host["id"] for host in cps_hosts}
                cinder_driver_cfg, cluster_name = cinder_driver_info
                logger.info('cluster name:{}'.format(cluster_name))
                old_section_list = cinder_driver_cfg.get('section_list')
                old_fs_agent = cinder_driver_cfg.get('fusionstorageagent')
                enabled_backend = cinder_driver_cfg.get('enabled_backend')
                old_compute_ip_list = old_fs_agent.split(",")
                old_compute_id_list = [all_host_ids[om_ip] for om_ip in old_compute_ip_list]
                self._merging_backend(old_section_list, section_list)
            compute_id_list, fs_agent = self.get_fs_agent_id_and_ip_info(obj, old_compute_id_list, old_compute_ip_list)

            logger.info('Start to get last uds image data')
            last_uds_data = obj.get_last_uds_image(resource_pool_data)
            config_cinder_args = [last_uds_data, add_new_pool, obj, enabled_backend,
                                  fs_agent, section_list, compute_id_list,
                                  private_key_psw, cluster_name]
            self._config_cinder_kvm(*config_cinder_args)

            logger.info("Start to check the interconnection result")
            cinder_kvm_name = obj.get_cinder_kvm_name_fusionstorage(self.az_id, enabled_backend)
            if not cinder_kvm_name:
                err_msg = "Failed to interconnect with cinder-kvm00x."
                logger.error(err_msg)
                raise FCDException(626006, err_msg)

            logger.info("Config Cinder connect with DistributedStorage success.")
            return Message(200)
        except FCDException as e:
            logger.error(traceback.format_exc())
            return Message(500, e)
        except Exception as e:
            logger.error(traceback.format_exc())
            return Message(500, FCDException(626006, str(e)))

    def get_fs_agent_id_and_ip_info(self, obj, old_compute_id_list, old_compute_ip_list):
        compute_ip_list = [vbs['om_ip'] for vbs in self.vbs_list]
        compute_id_list = [vbs['hostname'] for vbs in self.vbs_list]
        compute_ip_list = self._merging_compute(old_compute_ip_list, compute_ip_list)
        compute_id_list = self._merging_compute(old_compute_id_list, compute_id_list)
        max_host_num = 3
        if self.bms_condition:
            control_ip_list, control_id_list, compute_ip_list, compute_id_list = obj.get_hosts_info_u()
            bms_info = OpenStackNodeManager.get_bms_info(self.db, self.pod_id)
            compute_ip_list = [unit["bms_external_om_ip"] for unit in bms_info]
            compute_ip_list = self._merging_compute(old_compute_ip_list, compute_ip_list)
            control_id_list = self._merging_compute(old_compute_id_list, control_id_list)
            max_vbs_num = 2
            compute_ip_list = compute_ip_list[:max_vbs_num]
            if len(control_ip_list) > 0:
                compute_ip_list.append(control_ip_list[0])
            fs_agent = ",".join(compute_ip_list)
            control_id_list = control_id_list[:max_host_num]
            logger.info('control nodes id: {}, compute nodes ip: {}'.format(control_id_list, fs_agent))
            return control_id_list, fs_agent
        else:
            max_vbs_num = 3
            compute_ip_list = compute_ip_list[:max_vbs_num]
            fs_agent = ",".join(compute_ip_list)
            compute_id_list = compute_id_list[:max_host_num]
            logger.info('compute nodes id: {}, compute nodes ip: {}'.format(compute_id_list, fs_agent))
            return compute_id_list, fs_agent

    def multi_backend_name_config_check(self, multi_backend, cinder_cluster_data):
        if get_project_condition_boolean(self.project_id, 'TenantStorNewPool'):
            # 新增业务存储-新增存储池场景，LLD表填写的az内应存在cinder-kvm00X
            cluster_info = self.query_cinder_driver_info_by_az_id(cinder_cluster_data, self.az_id)
            if not cluster_info:
                err_msg = 'Error: The cinder-kvm service does not exist in the az [{}]'.format(self.az_id)
                logger.error(err_msg)
                raise FCDException(626381, self.az_id, self.az_id)
            cinder_driver_info = cluster_info["params"]["cinder_drivers"][0]["cfg"], cluster_info["params"]['host']
            return True, cinder_driver_info
        else:
            # 部署工程，扩AZ，IPSAN扩DistributedStorage场景，通过az_id和后端存储名不应查到cinder-kvm，即后端存储配置名称应不存在
            exist_cluster_name = dict()
            for cur_backend_name in multi_backend:
                cinder_kvm_name = self.query_cinder_kvm_by_az_id_and_backend_name(
                    cinder_cluster_data, self.az_id, cur_backend_name)
                if cinder_kvm_name:
                    exist_cluster_name[cur_backend_name] = cinder_kvm_name
            if exist_cluster_name:
                err_msg = 'Error: the backend [{}] already exists'.format(exist_cluster_name)
                logger.error(err_msg)
                raise FCDException(626382, self.az_id, exist_cluster_name, self.az_id)
        return False, ''

    def get_storage_pool_name_id_map(self):
        logger.info('Start to query storage pool')
        status_code, error_code, error_des = self.opr.login(DeployConstant.DM_LOGIN_USER, self.update_pwd)
        if status_code != 200 or error_code != 0:
            err_msg = "Failed to login deploy manager, " \
                      "Detail:[status:%s,code:%s] %s" % (status_code, error_code, error_des)
            logger.error(err_msg)
            raise FCDException(626067, err_msg)
        logger.info("Query storage pool data.")
        res_pool = self.opr.query_storage_pool()
        pool_info = res_pool.get_query_data()
        storage_pools = pool_info.get('storagePools')
        if len(storage_pools) == 0:
            err_msg = "Failed to query storage pool information."
            logger.error(err_msg)
            self.opr.login_out(DeployConstant.DM_LOGIN_USER, self.update_pwd)
            raise FCDException(626078, err_msg)
        pool_name_id_map = dict((cur_info.get('poolName'), cur_info.get('poolId')) for cur_info in storage_pools)
        self.opr.login_out(DeployConstant.DM_LOGIN_USER, self.update_pwd)
        logger.info('Result:{}'.format(pool_name_id_map))
        return pool_name_id_map

    @staticmethod
    def query_cinder_kvm_by_az_id_and_backend_name(cluster_data, availability_zone, enabled_backend):
        """
        :param cluster_data:
        :param availability_zone:
        :param enabled_backend:
        :return: cinder-kvm00x

        """
        cluster_list = cluster_data.get('cluster_list')
        if not cluster_list:
            logger.info('The cinder kvm service does not exist')
            return
        for cluster in cluster_list:
            cinder_drivers = cluster["params"]["cinder_drivers"]
            if not cinder_drivers:
                continue
            backend_store = cinder_drivers[0]["backend_store"]
            cur_az = cinder_drivers[0]["cfg"]["availability_zone"]
            if backend_store != 'fusionstorage' or cur_az != availability_zone:
                continue
            section_list = cinder_drivers[0]["cfg"]['section_list']
            for section in section_list:
                if section['volume_backend_name'] == enabled_backend:
                    cinder_kvm = cluster["params"]["host"]
                    logger.info('availability zone:{}, backend name:{}, exist cinder-kvm:{}'.format(
                        availability_zone, enabled_backend, cinder_kvm))
                    return cinder_kvm
        logger.info('The cinder kvm service does not exist')

    @staticmethod
    def query_cinder_driver_info_by_az_id(cluster_data, availability_zone):
        cluster_list = cluster_data.get('cluster_list')
        if not cluster_list:
            logger.info('The cinder kvm service does not exist, az id:{}'.format(availability_zone))
            return
        for cluster in cluster_list:
            cinder_drivers = cluster["params"]["cinder_drivers"]
            if not cinder_drivers:
                continue
            backend_store = cinder_drivers[0]["backend_store"]
            cur_az = cinder_drivers[0]["cfg"]["availability_zone"]
            if backend_store == 'fusionstorage' and cur_az == availability_zone:
                cinder_kvm = cluster["params"]["host"]
                logger.info('availability zone:{}, exist cinder-kvm:{}'.format(availability_zone, cinder_kvm))
                return cluster
        logger.info('The cinder kvm service does not exist, az id:{}'.format(availability_zone))

    @staticmethod
    def _merging_compute(old_compute_list, compute_list):
        compute_list = old_compute_list + compute_list
        compute_list_result = list()
        for compute in compute_list:
            if compute not in compute_list_result:
                compute_list_result.append(compute)
        return compute_list_result

    def get_business_backend_count(self):
        project_conditions = get_project_conditions(self.project_id)
        backend_count = 1
        for index in range(2, DeployConstant.MAX_BUSINESS_BACKEND + 1):
            if project_conditions.get('MultiTenantFB80StoragePool{}'.format(index)):
                backend_count += 1
            else:
                break
        return backend_count

    def get_multiple_backend_section(self, pool_name_id_dict):
        section_list = list()
        multi_backend = list()
        business_backend_count = self.get_business_backend_count()
        for index in range(1, business_backend_count + 1):
            backend_x = self._param_suffix('business_enabled_backend', index)
            pool_x = self._param_suffix('business_storage_pool', index)
            rate_x = self._param_suffix('business_thin_alloc_rate', index)
            backend = self.db.get_value_from_cloudparam(self.pod_id, "DistributedStorageBusiness", backend_x)
            backend_pools = self.db.get_value_from_cloudparam(self.pod_id, "DistributedStorageBusiness", pool_x)
            over_ratio = self.db.get_value_from_cloudparam(self.pod_id, "DistributedStorageBusiness", rate_x)
            if not backend or not backend_pools or not over_ratio:
                err_msg = "Some or all backend parameters are empty. Parameters: %s:%s, %s:%s, %s:%s" \
                          % (backend_x, backend, pool_x, backend_pools, rate_x, over_ratio)
                logger.error(err_msg)
                raise FCDException(626006, err_msg)
            logger.info("Get the index[%s] of backend info, backend_x:%s, pool_x:%s, rate_x:%s"
                        % (index, backend_x, pool_x, rate_x))
            pool_id_list = list()
            not_exist_pools = list()
            pool_name_list = backend_pools.split(',')
            for pool_name in pool_name_list:
                pool_id = pool_name_id_dict.get(pool_name)
                if pool_id is None:
                    logger.error("Not exist storage pool [%s] filled in the LLD." % pool_name)
                    not_exist_pools.append(pool_name)
                pool_id_list.append(str(pool_id))
            if len(not_exist_pools) > 0:
                err_msg = "Failed to query the storage pool ID based on the storage pool name[%s]. Exist pool:%s" \
                          % (','.join(not_exist_pools), pool_name_id_dict)
                logger.error(err_msg)
                raise FCDException(626006, err_msg)

            section = {"volume_backend_name": backend,
                       "pool_id_list": ','.join(pool_id_list),
                       "over_ratio": over_ratio}
            section_list.append(section)
            multi_backend.append(backend)
        logger.info("backend section list: %s " % section_list)
        return section_list, multi_backend

    @staticmethod
    def _param_suffix(parameter, suffix):
        if suffix == 1:
            return parameter
        else:
            return '{}_{}'.format(parameter, suffix)

    @staticmethod
    def _merging_backend(old_section_list, section_list):
        backend_list = [section.get('volume_backend_name') for section in section_list]
        logger.info("old section list: %s" % old_section_list)
        logger.info("section list: %s" % section_list)
        logger.info("backend list: %s" % backend_list)
        reserved_backend = list()
        for old_section in old_section_list:
            old_backend = old_section.get('volume_backend_name')
            if old_backend not in backend_list:
                reserved_backend.append(old_section)
                continue
            for section in section_list:
                backend = section.get('volume_backend_name')
                if old_backend != backend:
                    continue
                logger.info("meraging old backend: %s, backend: %s" % (old_backend, backend))
                pool_ids = section.get('pool_id_list')
                pool_id_list = pool_ids.split(',')
                old_pool_ids = old_section.get('pool_id_list')
                old_pool_id_list = old_pool_ids.split(',')
                pool_id_list = list(set(pool_id_list).union(set(old_pool_id_list)))
                section['pool_id_list'] = ','.join(pool_id_list)
        section_list.extend(reserved_backend)
        logger.info("merged backend list: %s" % section_list)

    def transfer_uds_key(self, uds_data):
        cps_client = FSPAuthClient.get_cps_rest_client(self.db, self.project_id, self.pod_id)
        uds_service = "glance"
        usd_template = "glance"
        uds_info = cps_client.get_template_params(uds_service, usd_template)
        uds_data_ak = uds_info.get("s3_store_access_key")
        uds_data_sk = uds_info.get("s3_store_secret_key")
        first_node_ip = FSPAuthClient.get_ssh_control_ip(self.db, self.project_id, self.pod_id)
        ssh_client = self.get_fsp_ssh_client(self.pod_id, first_node_ip)
        access_key, secret_key = self._decrypt_obs(ssh_client, uds_data_ak, uds_data_sk)
        logger.info("decrypt access and secret key successfully!")
        uds_data["s3_store_access_key_cinder"] = access_key
        uds_data["s3_store_secret_key_cinder"] = secret_key

    def _config_cinder_kvm(self, *args):
        last_uds_data, add_new_pool, obj,\
            enabled_backend, fs_agent, section_list,\
            compute_id_list, private_key_psw, cluster_name = args
        logger.info("Start to config Cinder connect with DistributedStorage.")
        if not last_uds_data:
            logger.info("Config the image type with glance")
            if add_new_pool:
                logger.info("Update Cinder connect with DistributedStorage")
                obj.update_resource_kvm_multiple_backend(
                    enabled_backend, self.float_ip, fs_agent, section_list, compute_id_list, self.az_id,
                    private_key_psw, cluster_name)
            else:
                logger.info("Config Cinder connect with DistributedStorage")
                obj.config_resource_kvm_multiple_backend(
                    enabled_backend, self.float_ip, fs_agent, section_list, compute_id_list, self.az_id,
                    private_key_psw)
        else:
            self.transfer_uds_key(last_uds_data)
            logger.info("Config the image type with uds")
            if add_new_pool:
                obj.update_resource_kvm_multiple_backend(
                    enabled_backend, self.float_ip, fs_agent, section_list, compute_id_list, self.az_id,
                    private_key_psw, cluster_name, last_uds_data)
            else:
                obj.config_kvm_multiple_backend_with_obs(
                    enabled_backend, self.float_ip, fs_agent, section_list, compute_id_list, self.az_id,
                    last_uds_data, private_key_psw)

    @staticmethod
    def get_fsp_ssh_client(pod_id, ip):
        """ Get FusionSphere Openstack ssh client

        steps of get fusionSphere openstack ssh client:
            1. logining with fsp.
            2. switching to root
            3. importing openstack environment

        :param pod_id: openstack pod id
        :param ip:
        :return: ssh_client
        """
        logger.info("Get host's(%s) ssh logined client" % ip)
        ssh_client_cmd = None
        try:
            fsp_pass_manager = FSPasswordManager(pod_id)
            fsp_password = fsp_pass_manager.get_fsp_password()
            ssh_client_cmd = Ssh.ssh_create_client(ip, "fsp", fsp_password)

            root_password = fsp_pass_manager.get_root_password()
            Ssh.ssh_send_command(ssh_client_cmd, "su", 'Password:', 300)
            Ssh.ssh_send_command(ssh_client_cmd, root_password, '#', 300)

            env_os_password = fsp_pass_manager.get_env_os_password()
            Ssh.ssh_send_command(ssh_client_cmd, "source set_env", '1|2', 300)
            Ssh.ssh_send_command(ssh_client_cmd, "1", 'OS_USERNAME', 300)
            Ssh.ssh_send_command(ssh_client_cmd, env_os_password, '#', 300)
        except Exception as err:
            logger.error('Get host(%s) logined client failed.reason=%s' % (ip, err))
            return ssh_client_cmd
        logger.info('Get host(%s) logined client success' % ip)
        return ssh_client_cmd

    @staticmethod
    def _decrypt_obs(ssh_client, s3_store_access_key_for_cinder, s3_store_secret_key_for_cinder):
        cmd_set = "rm /home/fsp/get_key_for_cinder.py"
        Ssh.ssh_send_command(ssh_client, cmd_set, '#', 300)
        cmd_set0 = "echo '"
        cmd_set1 = "' >> /home/fsp/get_key_for_cinder.py"
        cmd_set = "# -*- coding: utf-8 -*-"
        Ssh.ssh_send_command(ssh_client, cmd_set0 + cmd_set + cmd_set1, '#', 300)
        cmd_set = "from FSSecurity import crypt"
        Ssh.ssh_send_command(ssh_client, cmd_set0 + cmd_set + cmd_set1, '#', 300)
        cmd_set = 'access_key = "%s"' % s3_store_access_key_for_cinder
        Ssh.ssh_send_command(ssh_client, cmd_set0 + cmd_set + cmd_set1, '#', 300)
        cmd_set = 'secret_key = "%s"' % s3_store_secret_key_for_cinder
        Ssh.ssh_send_command(ssh_client, cmd_set0 + cmd_set + cmd_set1, '#', 300)
        cmd_set = 'print(access_key + "||" + crypt.decrypt(secret_key))'
        Ssh.ssh_send_command(ssh_client, cmd_set0 + cmd_set + cmd_set1, '#', 300)
        cmd_set = "python /home/fsp/get_key_for_cinder.py"
        listout = Ssh.ssh_send_command(ssh_client, cmd_set, '#', 300)
        cmd_set = "rm /home/fsp/get_key_for_cinder.py"
        Ssh.ssh_send_command(ssh_client, cmd_set, '#', 300)
        if listout[1]:
            out = listout[1].strip().split("||")
            if len(out) >= 2:
                logger.info("Decrypt obs-info success.")
                return out[0], out[1]
            else:
                logger.info("Decrypt obs-info failed, %s" % listout)
                raise Exception("Decrypt obs-info failed.")
        else:
            logger.error("Decrypt obs-info failed.")
            raise Exception("Decrypt obs-info failed.")

    def rollback_procedure(self):
        """
        新增业务存储-新增存储池场景：
            LLD表规划的后端名和pool_id存在：若对接的pool_id，都是LLD表存储池对应的pool_id，删后端；否则删除pool_id，不删后端
        部署工程、扩AZ、san扩fs场景：az内的cinder-kvm00X不应存在lld表填写的后端存储名。回滚查到cinder-kvm00X存在则删除
        :return:
        """
        try:
            logger.info('Query multiple backend name in the LLD')
            pool_name_id_dict = self.get_storage_pool_name_id_map()
            section_list, multi_backend = self.get_multiple_backend_section(pool_name_id_dict)

            logger.info("Get rollback params")
            webui_client = FSPAuthClient.get_cps_web_client(self.db, self.project_id, self.pod_id)
            obj = ConfinCascadingKvm(webui_client)
            resource_pool_data = obj.get_kvm_resource_pool()
            new_pool, cluster_info = self.rollback_get_multi_backend_params(
                multi_backend, resource_pool_data, section_list)

            logger.info('Execute rollback')
            if not cluster_info:
                logger.info("Rollback end")
                return Message(200)
            if new_pool:
                cluster_name, enabled_backend, fs_agent, update_section_list, proxy_hosts = cluster_info
                logger.info('This is the increase storage pool scenario, update {}'.format(cluster_name))

                logger.info('Upload certificates and get private key')
                private_key_psw = self.install_opr.upload_cert_and_get_private_key(webui_client)

                logger.info('Get last uds image data')
                last_uds_data = obj.get_last_uds_image(resource_pool_data)

                logger.info('Update cinder connect')
                if last_uds_data:
                    self.transfer_uds_key(last_uds_data)
                    obj.update_resource_kvm_multiple_backend(
                        enabled_backend, self.float_ip, fs_agent, update_section_list, proxy_hosts, self.az_id,
                        private_key_psw, cluster_name, last_uds_data)
                else:
                    obj.update_resource_kvm_multiple_backend(
                        enabled_backend, self.float_ip, fs_agent, update_section_list, proxy_hosts, self.az_id,
                        private_key_psw, cluster_name)
            else:
                logger.info('This is ExpansionAZ-KVM scenario, Delete {}'.format(cluster_info))
                obj.delete_resource(cluster_info)

            logger.info("Rollback end")
            return Message(200)
        except FCDException as e:
            logger.error(traceback.format_exc())
            return Message(500, e)
        except Exception as e:
            logger.error(traceback.format_exc())
            return Message(500, FCDException(626006, str(e)))

    def rollback_get_multi_backend_params(self, multi_backend, cinder_cluster_data, section_list):
        if get_project_condition_boolean(self.project_id, 'TenantStorNewPool'):
            # 新增业务存储-新增存储池场景
            cluster_info = self.query_cinder_driver_info_by_az_id(cinder_cluster_data, self.az_id)
            if not cluster_info:
                return True, ''
            cluster_name = cluster_info["params"]['host']
            logger.info('The {} service exists in the {}'.format(cluster_name, self.az_id))
            cinder_driver_cfg = cluster_info["params"]["cinder_drivers"][0]["cfg"]
            exist_section_list = cinder_driver_cfg['section_list']
            update_section_list = self.rollback_get_section_list_while_new_pool(exist_section_list, section_list)
            if update_section_list:
                enabled_backend = cinder_driver_cfg['enabled_backend']
                fs_agent = cinder_driver_cfg['fusionstorageagent']
                proxy_hosts = cluster_info['proxy_hosts']
                return True, (cluster_name, enabled_backend, fs_agent, update_section_list, proxy_hosts)
            return True, ''
        else:
            # 部署工程、扩AZ、san扩fs场景
            backend_name = multi_backend[0]
            cluster_name = self.query_cinder_kvm_by_az_id_and_backend_name(
                cinder_cluster_data, self.az_id, backend_name)
            if cluster_name:
                logger.info('The {} service already exists'.format(cluster_name))
            return False, cluster_name

    @staticmethod
    def rollback_get_section_list_while_new_pool(exist_section_list, section_list):
        """
        LLD表后端名存在，且pool_id存在：若对接的pool_id，都是LLD表存储池对应的pool_id，删后端；否则删除pool_id，不删后端
        """
        section_dict = dict((section['volume_backend_name'], section['pool_id_list']) for section in section_list)
        update_section_list = list()
        for exist_section in exist_section_list:
            if exist_section['volume_backend_name'] not in section_dict.keys():
                update_section_list.append(exist_section)
            else:
                exist_pool_id = set(exist_section['pool_id_list'].split(','))
                lld_pool_id = set(section_dict[exist_section['volume_backend_name']].split(','))
                pub_id = exist_pool_id.intersection(lld_pool_id)
                if not pub_id:
                    continue
                if len(pub_id) == len(exist_pool_id):
                    logger.info('Delete {}'.format(exist_section['volume_backend_name']))
                else:
                    update_pool_id = ','.join(exist_pool_id.difference(pub_id))
                    exist_section['pool_id_list'] = update_pool_id
                    update_section_list.append(exist_section)
        logger.info('update section list:{}'.format(update_section_list))
        return update_section_list
