package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.acd.ims.symphony.resource.VendorAuthenticationValidator;
import com.bocloud.acd.ims.symphony.sync.SyncOrchestrator;
import com.bocloud.cmp.driver.common.AuthDriver;
import com.bocloud.cmp.driver.common.LocationDriver;
import com.bocloud.cmp.entity.enums.AlarmTargetCatalog;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.model.Butler;
import com.bocloud.cmp.model.CloudVendorBean;
import com.bocloud.cmp.model.powervc.PowervcConstant;
import com.bocloud.cmp.provider.ButlerRepository;
import com.bocloud.common.encrypt.AESEncrptor;
import com.bocloud.common.encrypt.DESEncrptor;
import com.bocloud.common.encrypt.Encryptor;
import com.bocloud.common.enums.BaseStatus;
import com.bocloud.common.enums.BoCloudMethod;
import com.bocloud.common.enums.BoCloudService;
import com.bocloud.common.model.*;
import com.bocloud.common.utils.*;
import com.bocloud.ims.common.utils.constant.Constant;
import com.bocloud.ims.entity.common.Dictionary;
import com.bocloud.ims.entity.common.*;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.fusionsphere.FusionSphereStorageDevice;
import com.bocloud.ims.entity.resource.horizon.VmwareHorizonVcenterRelation;
import com.bocloud.ims.interfaces.resource.CloudVendorService;
import com.bocloud.ims.interfaces.resource.SyncService;
import com.bocloud.ims.interfaces.scheduler.CloudVendorTaskService;
import com.bocloud.ims.interfaces.scheduler.SnapshotTaskService;
import com.bocloud.ims.repository.kubernetes.*;
import com.bocloud.ims.repository.manageone.ManageOneAccountRepository;
import com.bocloud.ims.repository.manageone.ManageOneProjectRepository;
import com.bocloud.ims.repository.manageone.ManageOneVdcRepository;
import com.bocloud.ims.repository.pbm.PbmProfileRepository;
import com.bocloud.ims.repository.powervc.HostSeaRepository;
import com.bocloud.ims.repository.powervc.NetworkSeaRepository;
import com.bocloud.ims.repository.powervc.PowervcHmcRepository;
import com.bocloud.ims.repository.powervc.PowervcHmcServerRepository;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.repository.resource.azure.account.BatchAccountRepository;
import com.bocloud.ims.repository.resource.azure.account.StorageAccountRepository;
import com.bocloud.ims.repository.resource.f5.*;
import com.bocloud.ims.repository.resource.fusionsphere.*;
import com.bocloud.ims.repository.resource.horizon.*;
import com.bocloud.ims.service.internal.CosInternalService;
import com.bocloud.ims.service.internal.SmsDictionaryService;
import com.bocloud.ims.service.internal.SmsTenantService;
import com.bocloud.ims.service.resource.hmc.HmcDatabaseHelper;
import com.bocloud.ims.service.task.ResourceTaskNotice;
import com.bocloud.ims.service.transporter.vendor.SmartxTransporter;
import com.bocloud.ims.service.utils.LicenseSerivce;
import com.bocloud.ims.service.utils.ProviderRegister;
import com.bocloud.service.core.CurrentService;
import com.bocloud.service.http.core.ServiceFactory;
import com.bocloud.service.http.model.RemoteService;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * CloudVendor Service实现类
 *
 * @author ymh
 */
@Service("cloudVendorService")
public class CloudVendorServiceImpl implements CloudVendorService {

    private Logger logger = LoggerFactory.getLogger(CloudVendorServiceImpl.class);
    @Value("${upload.storage.path:/home/cmp}")
    private String uploadPath;
    @Value("${plarform.sync.schedule:0 0 0 * * ?}")
    private String defaultExpression;
    @Autowired
    private ServiceFactory serviceFactory;
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private CloudServerRepository cloudServerRepository;
    @Autowired
    private ImageRepository imageRepository;
    @Autowired
    private SnapshotRepository snapshotRepository;
    @Autowired
    private NetworkRepository networkRepository;
    @Autowired
    private VdcRepository vdcRepository;
    @Autowired
    private ClusterRepository clusterRepository;
    @Autowired
    private ServerRepository serverRepository;
    @Autowired
    private DataStoreRepository dataStoreRepository;
    @Autowired
    private StorageRepository storageRepository;
    @Autowired
    private StoreHostRepository storeHostRepository;
    @Autowired
    private ResourceAlarmRepository alarmRepository;
    @Autowired
    private NetworkCardRepository networkCardRepository;
    @Autowired
    private PowervcHmcServerRepository powervcHmcServerRepository;
    @Autowired
    private PowervcHmcRepository powervcHmcRepository;
    @Autowired
    private HostSeaRepository hostSeaRepository;
    @Autowired
    private SanFabricRepository sanFabricRepository;
    @Autowired
    private VolumeTemplateRepository volumeTemplateRepository;
    @Autowired
    private NetworkSeaRepository networkSeaRepository;
    @Autowired
    private FlavorExtraSpecsRepository flavorExtraSpecsRepository;
    @Autowired
    private ImageVolumeRepository imageVolumeRepository;
    @Autowired
    private AuthDriver authDriver;
    @Autowired
    private RouterRepository routerRepository;
    @Autowired
    private NetworkHostRepository networkHostRepository;
    @Autowired
    private PortGroupRepository portGroupRepository;
    @Autowired
    private SyncService syncService;
    @Autowired
    private ServerConfigRepository serverConfigRepository;
    @Autowired
    private FirewallRepository firewallRepository;
    @Autowired
    private FirewallPolicyRepository firewallPolicyRepository;
    @Autowired
    private FirewallRuleRepository firewallRuleRepository;
    @Autowired
    private IpRepository ipRepository;
    @Autowired
    private IpPoolRepository ipPoolRepository;
    @Autowired
    private ResourceRepository resourceRepository;
    @Autowired
    private LoadBalancerRepository loadBalancerRepository;
    @Autowired
    private LbListenerRepository lbListenerRepository;
    @Autowired
    private LbPoolRepository lbPoolRepository;
    @Autowired
    private HealthMonitorRepository healthMonitorRepository;
    @Autowired
    private ZoneRepository zoneRepository;
    @Autowired
    private LbMemberRepository lbMemberRepository;
    @Autowired
    private KeypairRepository KeypairRepository;
    @Autowired
    private ResourcePoolRepository resourcePoolRepository;
    @Autowired
    private SwitcherRepository switcherRepository;
    @Autowired
    private ProviderRegister providerRegister;
    @Autowired
    private AlarmThresholdRepository alarmThresholdRepository;
    @Autowired
    private DataStoreFileRepository dataStoreFileRepository;
    @Autowired
    private HmcDatabaseHelper hmcDatabaseHelper;
    @Autowired
    private F5BiVirtualServerRepository f5BiVirtualServerRepository;
    @Autowired
    private F5BiPoolRepository f5BiPoolRepository;
    @Autowired
    private F5BiNodeRepository f5BiNodeRepository;
    @Autowired
    private F5BiProfileRepository f5BiProfileRepository;
    @Autowired
    private F5BiMonitorRepository f5BiMonitorRepository;
    @Autowired
    private F5BiPoolMemberRepository f5BiPoolMemberRepository;
    @Autowired
    private F5BiDnsResolversRepository f5BiDnsResolversRepository;
    @Autowired
    private F5BiIRulesRepository f5BiIRulesRepository;
    @Autowired
    private F5BiSnatPoolRepository f5BiSnatPoolRepository;
    @Autowired
    private F5BiVlanRepository f5BiVlanRepository;
    @Autowired
    private F5BiTunnelRepository f5BiTunnelRepository;
    @Autowired
    private VpcRepository vpcRepository;
    @Autowired
    private PoolGroupRepository poolGroupRepository;
    @Autowired
    private ServerKeypairRepository serverKeypairRepository;
    @Autowired
    private ServerSgroupRepository serverSgroupRepository;
    @Autowired
    private StorageAccountRepository storageAccountRepository;
    @Autowired
    private VolumePoolRepository volumePoolRepository;
    @Autowired
    private ServerVolumeRepository serverVolumeRepository;
    @Autowired
    private KubeNamespaceRepository namespaceRepository;
    @Autowired
    private KubeContainerRepository kubeContainerRepository;
    @Autowired
    private KubeDaemonSetRepository kubeDaemonSetRepository;
    @Autowired
    private KubeNodeLabelRepository kubeNodeLabelRepository;
    @Autowired
    private KubePersistentVolumeClaimRepository kubePersistentVolumeClaimRepository;
    @Autowired
    private KubeSecretRepository kubeSecretRepository;
    @Autowired
    private BatchAccountRepository batchAccountRepository;
    @Autowired
    private KubeNodeRepository nodeRepository;
    @Autowired
    private KubePodRepository podRepository;
    @Autowired
    private KubeServiceRepository serviceRepository;
    @Autowired
    private KubeDeploymentRepository kubeDeploymentRepository;
    @Autowired
    private KubePersistentVolumeRepository persistentVolumeRepository;
    @Autowired
    private BackupVaultsRepository backupVaultsRepository;
    @Autowired
    private BackupRepository backupRepository;
    @Autowired
    private SmsTenantService smsTenantService;
    @Autowired
    private PoolGroupZoneRepository poolGroupZoneRepository;
    @Autowired
    private SmsDictionaryService smsDictionaryService;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private CurrentService currentService;
    @Autowired
    private VolumeTypeRepository volumeTypeRepository;
    @Autowired
    private ResourceGroupRepository resourceGroupRepository;
    @Autowired
    private NetworkInterfaceRepository networkInterfaceRepository;
    @Autowired
    private CosInternalService cosInternalService;
    @Autowired
    private CloudVendorStatisticsRepository cloudVendorStatisticsRepository;
    @Autowired
    private OSTenantRepository osTenantRepository;
    @Autowired
    private KeypairRepository keypairRepository;
    @Autowired
    private VolumeRepository volumeRepository;
    @Autowired
    private FlavorRepository flavorRepository;
    @Autowired
    private PortRepository portRepository;
    @Autowired
    private PortFixedIpRepository portFixedIpRepository;
    @Autowired
    private SubnetRepository subnetRepository;
    @Autowired
    private SecurityGroupRepository securityGroupRepository;
    @Autowired
    private SecurityGroupRuleRepository securityGroupRuleRepository;
    @Autowired
    private TenantNetworkRepository tenantNetworkRepository;
    @Autowired
    private RegionRepository regionRepository;
    @Autowired
    private FloatingIpRepository floatingIpRepository;
    @Autowired
    private CloudStackRepository cloudStackRepository;
    @Autowired
    private CloudStackEventRepository cloudStackEventRepository;
    @Autowired
    private AutoScalingRepository autoScalingRepository;
    @Autowired
    private AutoScalingConfigRepository autoScalingConfigRepository;
    @Autowired
    private QosPolicyRepository qosPolicyRepository;
    @Autowired
    private QosPolicyRulesRepository qosPolicyRulesRepository;
    @Autowired
    private AutoScalingAlarmTaskRepository autoScalingAlarmTaskRepository;
    @Autowired
    private PbmProfileRepository pbmProfileRepository;
    @Autowired
    private ManageOneVdcRepository manageOneVdcRepository;
    @Autowired
    private ManageOneProjectRepository manageOneProjectRepository;
    @Autowired
    private ManageOneAccountRepository manageOneAccountRepository;
    @Autowired
    private ScsiLunRepository lunRepository;
    @Autowired
    private IpPoolPortGroupRepository ipPoolPortGroupRepository;
    @Autowired
    private CloudVendorTaskService cloudVendorTaskService;
    /**
     * vmware horizon
     */
    @Autowired
    private VmwareHorizonDesktopPoolRepository desktopPoolRepository;
    @Autowired
    private VmwareHorizonSessionRepository sessionRepository;
    @Autowired
    private VmwareHorizonUserOrGroupRepository userOrGroupRepository;
    @Autowired
    private VmwareHorizonVcenterRepository vcenterRepository;
    @Autowired
    private VmwareHorizonFarmRepository farmRepository;
    @Autowired
    private VmwareHorizonVcenterRelationRepository vcenterRelationRepository;
    @Autowired
    private InternetGatewayRepository internetGatewayRepository;
    @Autowired
    private ElasticIpRepository elasticIpRepository;
    @Autowired
    private TagRepository tagRepository;
    @Autowired
    private NatGatewayRepository natGatewayRepository;
    @Autowired
    private NatGatewaySnatRuleRepository natGatewaySnatRuleRepository;
    @Autowired
    private NatGatewayDnatRuleRepository natGatewayDnatRuleRepository;
    @Autowired
    private RouteRepository routeRepository;
    @Autowired
    private RouteTableRepository routeTableRepository;
    @Autowired
    private SnapshotTaskService snapshotTaskService;
    @Autowired
    private CidrBlockRepository cidrBlockRepository;
    @Autowired
    private SmartxTransporter smartTransporter;
    @Autowired
    private LocationDriver locationDriver;
    @Autowired
    private FusionSphereOsVersionRepository osVersionRepository;
    @Autowired
    private FusionSphereHostPortRepository hostPortRepository;
    @Autowired
    private FusionSphereStorageDeviceRepository storageDeviceRepository;
    @Autowired
    private FusionSphereDeviceHostRepository deviceHostRepository;
    @Autowired
    private PoolGroupRelationRepository poolGroupRelationRepository;
    @Autowired
    private FusionSphereUpLinkRepository upLinkRepository;
    @Autowired
    private FusionSphereVlanPoolRepository vlanPoolRepository;
    @Autowired
    private FusionSphereUpLinkPortRepository upLinkPortRepository;
    @Autowired
    private PortGroupRelationRepository portGroupRelationRepository;
    @Autowired
    private CloudBillRepository cloudBillRepository;
    @Autowired
    private LicenseSerivce licenseSerivce;
    @Autowired
    private ResourceTaskNotice resourceTaskNotice;

    @Autowired
    private VendorAuthenticationValidator vendorAuthenticationValidator;

    @Autowired
    private SyncOrchestrator syncOrchestrator;

    @Override
    public BocloudResult<CloudVendor> create(CloudVendor vendor, RequestContext context) {
        try {
            // 先进行同名认证，虽然输入时已验证，可能浏览器会记录信息
            CloudVendor existedVendor = cloudVendorRepository.getByName(vendor.getName());
            Assert.isNull(existedVendor, "添加失败，名称重复");
            String type = vendor.getType();
            String version = vendor.getVersion();
            if (type != null) {
                type = type.toUpperCase();
            }
            // 云平台认证信息
            JSONObject authentication = JSONObject.parseObject(vendor.getAuthentication());
            Assert.notNull(authentication, "平台认证信息参数有误");
            if (CloudProvider.OPENSTACK.name().equals(type) || CloudProvider.VMWARE.name().equals(type)
                    || CloudProvider.ALIYUN.name().equals(type) || CloudProvider.JDCLOUD.name().equals(type)
                    || CloudProvider.H3C.name().equals(type) || CloudProvider.HMC.name().equals(type)
                    || CloudProvider.FUSIONCLOUD.name().equals(type) || CloudProvider.MANAGEONE.name().equals(type)
                    || CloudProvider.TENCENT.name().equals(type) || CloudProvider.HUAWEI.name().equals(type)
                    || CloudProvider.XEN.name().equals(type) || CloudProvider.POWERVC.name().equals(type)
                    || CloudProvider.CLOUDOS.name().equals(type) || CloudProvider.AZURE.name().equals(type)
                    || CloudProvider.KINGCLOUD.name().equals(type) || CloudProvider.KUBERNETES.name().equals(type)
                    || CloudProvider.AWS.name().equals(type) || CloudProvider.QCLOUD.name().equals(type)
                    || CloudProvider.TCE.name().equals(type) || CloudProvider.PQCLOUD.name().equals(type)
                    || CloudProvider.TIANYI.name().equals(type) || CloudProvider.HCSO.name().equals(type)
                    || CloudProvider.FUSIONSPHERE.name().equals(type) || CloudProvider.EASYSTACK.name().equals(type)) {
                // 节点数校验
                int currentNode = currentService.getUsed();// 当前节点数
                int node = licenseSerivce.license().getNode();
                if (currentNode > node) {
                    return new BocloudResult<>(false, "当前系统节点数（宿主机和云主机）已超过license限制，云平台添加失败!", "500", "");
                }
            }
            if (!CloudProvider.JDCLOUD.name().equals(type) && !CloudProvider.ALIYUN.name().equals(type)
                    && !CloudProvider.TENCENT.name().equals(type) && !CloudProvider.HUAWEI.name().equals(type)
                    && !CloudProvider.XEN.name().equals(type) && !CloudProvider.KINGCLOUD.name().equals(type)
                    && !CloudProvider.AZURE.name().equals(type) && !CloudProvider.KUBERNETES.name().equals(type)
                    && !CloudProvider.AWS.name().equals(type) && !CloudProvider.QCLOUD.name().equals(type)
                    && !CloudProvider.TCE.name().equals(type) && !CloudProvider.PQCLOUD.name().equals(type)
                    && !CloudProvider.F5.name().equals(type) && !CloudProvider.TIANYI.name().equals(type)
                    && !CloudProvider.HCSO.name().equals(type) && !CloudProvider.MANAGEONE.name().equals(type)
                    && !CloudProvider.VOLCENGINE.name().equals(type) && !CloudProvider.FUSIONSPHERE.name().equals(type)
                    && (!CloudProvider.SANGFOR.name().equals(type) || (CloudProvider.SANGFOR.name().equals(type) && version.equals("6.3")))) {
                // 正则获取IP
                String address = authentication.getString("address");
                String regex = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}";
                Pattern p = Pattern.compile(regex);
                Matcher m = p.matcher(address);
                if (m.find()) {
                    address = m.group();
                }
                if (address.endsWith("/")) {
                    address = address.substring(0, address.length() - 1);
                }
                existedVendor = cloudVendorRepository.getByAddress(address);
                JSONObject oldAuthentication = new JSONObject();

                // 前端传过来的参数用AES解密
                Encryptor encryptor = new AESEncrptor();
                String password = encryptor.decrypt(authentication.getString("password").trim(), null);
                encryptor = new DESEncrptor();
                password = encryptor.encrypt(password, "BocloudCMP");
                authentication.put("password", password);

                if (null != existedVendor) {
                    oldAuthentication = JSONObject.parseObject(existedVendor.getAuthentication());
                }
                if (null != existedVendor
                        && authentication.getString("account").equals(oldAuthentication.getString("account"))
                        && password.equalsIgnoreCase(oldAuthentication.getString("password"))) {
                    return new BocloudResult<>(false, "此平台已存在，不能重复添加!");
                }
                if (CloudProvider.FUSIONCLOUD.name().equals(type)) {
                    authentication.put("projectName", authentication.getString("projectId"));
                }
            }
            if (CloudProvider.F5.name().equals(type)) {
                Encryptor encryptor = new AESEncrptor();
                String password = encryptor.decrypt(authentication.getString("password").trim(), null);
                encryptor = new DESEncrptor();
                password = encryptor.encrypt(password, "BocloudCMP");
                authentication.put("password", password);
            } else if (CloudProvider.TCE.name().equals(type)) {
                String regionId = authentication.getString("regionId");
                List<String> regions = new ArrayList<>();
                regions.add(regionId);
                authentication.put("regions", JSON.toJSONString(regions));
            } else if (CloudProvider.POWERVC.name().equals(type)) {
                String projectName = authentication.getString("projectName");
                if (StringUtils.isEmpty(projectName)) {
                    authentication.put("projectName", PowervcConstant.DEFAULT_PROJECT_NAME);
                }
                String domainName = authentication.getString("domainName");
                if (StringUtils.isEmpty(domainName)) {
                    authentication.put("domainName", PowervcConstant.DEFAULT_DOMAIN_NAME);
                }
            } else if (CloudProvider.MANAGEONE.name().equals(type)) {
                // 前端传过来的参数用AES解密
                Encryptor encryptor = new AESEncrptor();
                String password = encryptor.decrypt(authentication.getString("password").trim(), null);
                encryptor = new DESEncrptor();
                password = encryptor.encrypt(password, "BocloudCMP");
                authentication.put("password", password);
            } else if (CloudProvider.FUSIONSPHERE.name().equals(type)) {
                Encryptor encryptor = new AESEncrptor();
                String password = encryptor.decrypt(authentication.getString("password").trim(), null);
                encryptor = new DESEncrptor();
                password = encryptor.encrypt(password, "BocloudCMP");
                authentication.put("password", password);
            }
            if (CloudProvider.TCE.name().equals(type) || CloudProvider.ALIYUN.name().equals(type)
                    || CloudProvider.TENCENT.name().equals(type) || CloudProvider.QCLOUD.name().equals(type)
                    || CloudProvider.PQCLOUD.name().equals(type) || CloudProvider.KINGCLOUD.name().equals(type)
                    || CloudProvider.AWS.name().equals(type) || CloudProvider.AZURE.name().equals(type)
                    || CloudProvider.TIANYI.name().equals(type) || CloudProvider.HUAWEI.name().equals(type)
                    || CloudProvider.HCSO.name().equals(type) || CloudProvider.JDCLOUD.name().equals(type)
                    || CloudProvider.VOLCENGINE.name().equals(type)
                    || (CloudProvider.SANGFOR.name().equals(type) && version.equals("6.8"))) {
                String accessKey = null;
                String secretKey = null;
                if (authentication.containsKey("accessKey")) {
                    Encryptor encryptor = new AESEncrptor();
                    accessKey = encryptor.decrypt(authentication.getString("accessKey").trim(), null);
                    encryptor = new DESEncrptor();
                    accessKey = encryptor.encrypt(accessKey, "BocloudCMP");
                    authentication.put("accessKey", accessKey);
                }
                if (authentication.containsKey("secretKey")) {
                    Encryptor encryptor = new AESEncrptor();
                    secretKey = encryptor.decrypt(authentication.getString("secretKey").trim(), null);
                    encryptor = new DESEncrptor();
                    secretKey = encryptor.encrypt(secretKey, "BocloudCMP");
                    authentication.put("secretKey", secretKey);
                }
                // 平台重复性校验
                CloudVendor cloudVendor = null;
                if (CloudProvider.AZURE.name().equals(type)) {//微软云校验订阅
                    cloudVendor = cloudVendorRepository.getByAk(authentication.getString("tenant"), authentication.getString("subscriptionId"));
                } else {
                    cloudVendor = cloudVendorRepository.getByAk(accessKey, secretKey);
                }
                if (null != cloudVendor) {
                    return new BocloudResult<>(false, "当前认证信息平台已存在，无需重复添加");
                }
                String regions = authentication.getString("regions");
                List<String> currentRegions = JSONObject.parseArray(regions, String.class);
                if (!ListTool.isEmpty(currentRegions)) {
                    authentication.put("regionId", currentRegions.get(0));
                }
            }
            // 设置平台超分比 目前只有vc使用 其他平台不影响
            authentication.put("excessRatio", 1);
            // 重新设置封装后的认证信息
            vendor.setAuthentication(JSONObject.toJSONString(authentication));
            vendor.setStatus(BaseStatus.NORMAL.name());
            vendor.setUuid(KeyGenerator.uuid());
            // 在zk注册信息
            List<CloudVendor> list = cloudVendorRepository.listAll();
            list.add(vendor);
            this.providerRegister.updateProvider(list);
            // 新增云平台后需要等一会儿才会触发zookeeper的节点变化事件，然后ButlerRepository才会有新增的云平台数据
            Boolean flag = this.waitProviderCache(vendor.getUuid());
            Assert.isTrue(flag, "平台添加失败！");
            // 认证
            String regionId = authentication.getString("regionId") == null ? "" : authentication.getString("regionId");
            BocloudResult result = authDriver.auth(vendor.getUuid(), regionId);
            Assert.isTrue(result.isSuccess(), result.getMessage());
            vendor.setId(null);
            vendor.setSyncCron(StringUtils.isEmpty(vendor.getSyncCron()) ? defaultExpression : vendor.getSyncCron());
            String catalogIdsString = JSONObject.toJSONString(vendor.getCatalogIds());
            vendor.setCatalogIds(catalogIdsString.substring(1, catalogIdsString.length() - 1));
            cloudVendorRepository.save(vendor);
            // 开始同步平台资源数据
            syncService.sync(vendor.getId(), context, false);
            // 开启定时同步
            cloudVendorTaskService.create(vendor.getId(), context);
            // 开启拉取账单
//            if (CloudProvider.AZURE.name().equals(type)){
//                azureBillServiceUtils.syncAllBill(vendor);
//            }
            return new BocloudResult<>(true, vendor, "平台添加成功，正在同步数据中...");
        } catch (Exception e) {
            logger.error("create cloudVendor fail:", e);
            return new BocloudResult<>(false, "平台添加失败：" + e.getMessage());
        }
    }

    /**
     * 等待云平台新数据从zookeeper缓存到本地
     *
     * @param vendor
     * @return
     */
    private boolean waitProviderCache(String vendor) {
        Boolean flag = true;
        Long startTime = System.currentTimeMillis();
        while (flag) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                logger.error("Get error message:", e);
                Thread.currentThread().interrupt();
            }
            // 如果拉取到缓存数据，则说明已经添加成功
            Butler butler = ButlerRepository.getInstance().get(vendor);
            if (null != butler) {
                flag = false;
                return true;
            }
            Long endTime = System.currentTimeMillis();
            // 等待30秒
            if (endTime - startTime > 30 * 1000) {
                flag = false;
                break;
            }
        }
        return false;
    }

    @Transactional
    @Override
    public BocloudResult<CloudVendor> modify(CloudVendorBean bean, RequestContext context) {
        String path = CloudVendor.class.getSimpleName() + "_" + bean.getId();
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudVendor vendor = cloudVendorRepository.query(bean.getId());
            Assert.notNull(vendor, "数据不存在");
            Long userId = context.getTarget();
            if (!bean.getName().equals(vendor.getName())) {
                CloudVendor object = cloudVendorRepository.getByName(bean.getName());
                Assert.isNull(object, "名称不能重复!");
            }
            String availablitiyZone = bean.getAvailablitiyZone();
            if (null != availablitiyZone && !availablitiyZone.equals(vendor.getAvailablitiyZone())) {
                CloudVendor object = cloudVendorRepository.getByRegion(bean.getRegion(), bean.getAvailablitiyZone(),
                        CloudProvider.VMWARE.name());
                Assert.isNull(object, "当前可用域下已有其他云平台");
            }
            if (CloudProvider.KUBERNETES.name().equals(vendor.getType())) {
                Long oldHarborId = vendor.getHarborId();
                Long newHarborId = bean.getHarborId();
                if (null != oldHarborId && null != newHarborId && oldHarborId.equals(newHarborId)) {
                    CloudVendor cloudVendor = cloudVendorRepository.queryByBarborId(newHarborId);
                    Assert.isNull(cloudVendor, "当前仓库已被绑定，请选择其他仓库！");
                }
            }

            // 增加regionId的处理 sxp:2022-10-20
            JSONObject authenticationJson = JSONObject.parseObject(bean.getAuthentication());
            String regions = authenticationJson.getString("regions");
            if (StringUtils.isNotEmpty(regions)) {
                List<String> currentRegions = JSONObject.parseArray(regions, String.class);
                if (!ListTool.isEmpty(currentRegions)) {
                    authenticationJson.put("regionId", currentRegions.get(0));
                    String newAuthentication = authenticationJson.toJSONString();
                    bean.setAuthentication(newAuthentication);
                }
            }

            String catalogIdsString = bean.getCatalogIds();
            if (!StringUtils.isEmpty(catalogIdsString)) {
                bean.setCatalogIds(catalogIdsString.substring(1, catalogIdsString.length() - 1));
            }
            bean.setSyncCron(vendor.getSyncCron());
            BeanUtils.copyProperties(bean, vendor);
            vendor.setMenderId(userId);
            Boolean result = cloudVendorRepository.update(vendor);
            if (result) {
                // 在zk刷新注册信息
                List<CloudVendor> list = cloudVendorRepository.listAll();
                this.providerRegister.updateProvider(list);
            }
            String content = "修改成功";
            if (CloudProvider.ALIYUN.name().equals(vendor.getType()) || CloudProvider.TENCENT.name().equals(vendor.getType()) ||
                    CloudProvider.HUAWEI.name().equals(vendor.getType()) || CloudProvider.QCLOUD.name().equals(vendor.getType())
                    || CloudProvider.AWS.name().equals(vendor.getType()) || CloudProvider.HCSO.name().equals(vendor.getType())
                    || CloudProvider.AZURE.name().equals(vendor.getType())) {
                syncService.sync(vendor.getId(), context, false);
                content = "修改成功，正在进行数据同步...";
            }
            return result ? new BocloudResult<>(true, vendor, content)
                    : new BocloudResult<>(false, vendor, "修改失败");
        } catch (Exception e) {
            logger.error("modify cloudVendor fail:", e);
            return new BocloudResult<>(false, e.getMessage());
        }
    }

    @Transactional
    @Override
    public BocloudResult remove(Long id, RequestContext context) {
        String path = CloudVendor.class.getSimpleName() + "_" + id;
        boolean result = false;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudVendor vendor = cloudVendorRepository.query(id);
            Assert.notNull(vendor, "数据不存在");
            boolean isUse = cloudServerRepository.inUseByTenants(id);
            Assert.isTrue(!isUse, "无法删除：有租户资源在该平台上");
            BocloudResult bocloudResult = smsTenantService.checkPoolGroup(id);
            Assert.isTrue(bocloudResult.isSuccess(), bocloudResult.getMessage());
            JSONObject authentication = JSONObject.parseObject(vendor.getAuthentication());
            CloudProvider type = CloudProvider.valueOf(vendor.getType());
            if (CloudProvider.OPENSTACK.name().equals(vendor.getType())
                    || CloudProvider.EASYSTACK.name().equals(vendor.getType())
                    || CloudProvider.VMWARE.name().equals(vendor.getType())
                    || CloudProvider.H3C.name().equals(vendor.getType())
                    || CloudProvider.TENCENT.name().equals(vendor.getType())
                    || CloudProvider.HUAWEI.name().equals(vendor.getType())
                    || CloudProvider.HCSO.name().equals(vendor.getType())
                    || CloudProvider.AZURE.name().equals(vendor.getType())
                    || CloudProvider.AWS.name().equals(vendor.getType())
                    || CloudProvider.TCE.name().equals(vendor.getType())) {
                List<Network> networks = networkRepository.listByVid(id);
                for (Network network : networks) {
                    vpcRepository.deleteByNetworkId(network.getId(), context.getTarget());
                }
            }
            List<CloudServer> servers = cloudServerRepository.listByVid(id);
            List<Server> hosts = new ArrayList<>();
            switch (type) {
                case OPENSTACK:
                case EASYSTACK:
                case VMWARE:
                case FUSIONSPHERE:
                    hosts = serverRepository.listByVendor(id);
                    break;
                case POWERVC:
                    authDriver.removeAuthFromMemory(vendor.getUuid(), authentication.getString("address"),
                            authentication.getString("account"));

                    List<Server> serverList = serverRepository.listByVendor(id);
                    for (Server server : serverList) {
                        serverConfigRepository.removeBySid(server.getId());
                        powervcHmcServerRepository.removeByServer(server.getId());
                    }
                    powervcHmcRepository.removeByVendor(id, context.getTarget());
                    serverRepository.removeByVendor(id, context.getTarget());
                    hostSeaRepository.removeByVendor(id);
                    cloudServerRepository.removeByVid(id, context.getTarget());
                    serverVolumeRepository.removeByVendorid(id, context.getTarget());
                    storageRepository.removeByVendor(id);
                    sanFabricRepository.removeByVendor(id);
                    volumeTemplateRepository.removeByVendor(id);
                    volumeRepository.removeByVid(id, context.getTarget());
                    networkRepository.removeByVid(id, context.getTarget());
                    networkSeaRepository.deleteByVendorId(id);
                    subnetRepository.removeByVid(id, context.getTarget());
                    imageRepository.removeByVid(id, context.getTarget());
                    flavorRepository.removeByVid(id);
                    ipPoolRepository.removeByVid(id, context.getTarget());
                    ipRepository.deleteByVid(id);
                    portRepository.removeByVid(id, context.getTarget());
                    portFixedIpRepository.deleteByVendorId(id);
                    flavorExtraSpecsRepository.removeByVendorId(id);
                    clusterRepository.removeByVendor(id, context.getTarget());
                    volumePoolRepository.removeByVendor(id);
                    imageVolumeRepository.removeByVendorId(id, context.getTarget());
                    resourceRepository.removeByVid(id, context.getTarget());
                    break;
                default:
                    break;
            }
            switch (type) {
                case OPENSTACK:
                case EASYSTACK:
                    isUse = volumeRepository.inUseByTenants(id) || networkRepository.inUseByTenants(id)
                            || routerRepository.inUseByTenants(id) || securityGroupRepository.inUseByTenants(id)
                            || floatingIpRepository.inUseByTenants(id) || firewallRepository.inUseByTenants(id)
                            || firewallPolicyRepository.inUseByTenants(id) || firewallRuleRepository.inUseByTenants(id)
                            || loadBalancerRepository.inUseByTenants(id);
                    if (isUse) {
                        return new BocloudResult<>(false, "无法删除：有租户资源在该平台上");
                    }
                    KeypairRepository.removeByVid(id, context.getTarget());
                    lbMemberRepository.removeByVid(id, context.getTarget());
                    healthMonitorRepository.removeByVid(id, context.getTarget());
                    lbPoolRepository.removeByVid(id, context.getTarget());
                    lbListenerRepository.removeByVid(id, context.getTarget());
                    loadBalancerRepository.removeByVid(id, context.getTarget());
                    imageRepository.removeByVid(id, context.getTarget());
                    volumeRepository.removeByVid(id, context.getTarget());
                    snapshotRepository.removeByVid(id, context.getTarget());
                    flavorRepository.removeByVid(id);
                    List<Port> ports = portRepository.listByVid(id);
                    for (Port port : ports) {
                        portFixedIpRepository.deleteByPortId(port.getId());
                    }
                    portRepository.removeByVid(id, context.getTarget());
                    subnetRepository.removeByVid(id, context.getTarget());
                    networkRepository.removeByVid(id, context.getTarget());
                    routerRepository.removeByVid(id, context.getTarget());
                    alarmRepository.removeByVid(id, context.getTarget());
                    serverRepository.removeByVendor(id, context.getTarget());
                    resourceRepository.removeByVid(id, context.getTarget());
                    ipRepository.deleteByVid(id);
                    firewallRepository.removeByVid(id, context.getTarget());
                    firewallPolicyRepository.removeByVid(id, context.getTarget());
                    firewallRuleRepository.removeByVid(id, context.getTarget());
                    floatingIpRepository.removeByVid(id, context.getTarget());
                    securityGroupRepository.removeByVid(id, context.getTarget());
                    securityGroupRuleRepository.removeByVid(id, context.getTarget());
                    tenantNetworkRepository.deleteByVendor(id);
                    regionRepository.deleteByVid(id);
                    ipPoolRepository.removeByVid(id, context.getTarget());
                    volumeTypeRepository.deleteByVendorId(id);
                    osTenantRepository.removeByVid(id);
                    cloudStackRepository.removeByVid(id, context.getTarget());
                    cloudStackEventRepository.removeByStackId(null, id);
                    autoScalingRepository.remove(id, context.getTarget());
                    autoScalingConfigRepository.removeByVid(id, context.getTarget());
                    autoScalingAlarmTaskRepository.removeByVid(id, context.getTarget());
                    qosPolicyRepository.removeByVid(id, context.getTarget());
                    qosPolicyRulesRepository.removeByVid(id, context.getTarget());
                    keypairRepository.removeByVid(id, context.getTarget());
                    break;
                case FUSIONCLOUD:
                case MANAGEONE:
                    KeypairRepository.removeByVid(id, context.getTarget());
                    imageRepository.removeByVid(id, context.getTarget());
                    volumeRepository.removeByVid(id, context.getTarget());
                    snapshotRepository.removeByVid(id, context.getTarget());
                    flavorRepository.removeByVid(id);
                    List<Port> oldPorts = portRepository.listByVid(id);
                    for (Port port : oldPorts) {
                        portFixedIpRepository.deleteByPortId(port.getId());
                    }
                    portRepository.removeByVid(id, context.getTarget());
                    subnetRepository.removeByVid(id, context.getTarget());
                    networkRepository.removeByVid(id, context.getTarget());
                    routerRepository.removeByVid(id, context.getTarget());
                    serverRepository.removeByVendor(id, context.getTarget());
                    resourceRepository.removeByVid(id, context.getTarget());
                    ipRepository.deleteByVid(id);
                    securityGroupRepository.removeByVid(id, context.getTarget());
                    securityGroupRuleRepository.removeByVid(id, context.getTarget());
                    tenantNetworkRepository.deleteByVendor(id);
                    regionRepository.deleteByVid(id);
                    ipPoolRepository.removeByVid(id, context.getTarget());
                    if (CloudProvider.MANAGEONE == type) {
                        manageOneVdcRepository.removeByVendorId(id);
                        manageOneProjectRepository.removeByVendorId(id);
                        manageOneAccountRepository.removeByVendorId(id);
                    }
                    lbMemberRepository.removeByVid(id, context.getTarget());
                    healthMonitorRepository.removeByVid(id, context.getTarget());
                    lbPoolRepository.removeByVid(id, context.getTarget());
                    lbListenerRepository.removeByVid(id, context.getTarget());
                    loadBalancerRepository.removeByVid(id, context.getTarget());
                    alarmRepository.removeByVid(id, context.getTarget());
                    firewallRepository.removeByVid(id, context.getTarget());
                    firewallPolicyRepository.removeByVid(id, context.getTarget());
                    firewallRuleRepository.removeByVid(id, context.getTarget());
                    floatingIpRepository.removeByVid(id, context.getTarget());
                    volumeTypeRepository.deleteByVendorId(id);
                    osTenantRepository.removeByVid(id);
                    break;
                case VMWARE:
                    vdcRepository.removeByVendor(id, context.getTarget());
                    clusterRepository.removeByVendor(id, context.getTarget());
                    serverRepository.removeByVendor(id, context.getTarget());
                    dataStoreRepository.removeByVendor(id, context.getTarget());
                    storeHostRepository.removeByVendor(id);
                    snapshotRepository.removeByVid(id, context.getTarget());
                    networkRepository.removeByVid(id, context.getTarget());
                    networkCardRepository.removeByVid(id, context.getTarget());
                    alarmRepository.removeByVid(id, context.getTarget());
                    switcherRepository.removeByVid(id, context.getTarget());
                    networkHostRepository.removeByVendor(id);
                    portGroupRepository.removeByVid(id, context.getTarget());
                    imageRepository.removeByVid(id, context.getTarget());
                    resourceRepository.removeByVid(id, context.getTarget());
                    ipRepository.deleteByVid(id);
                    resourcePoolRepository.removeByVendorId(id, context.getTarget());
                    alarmThresholdRepository.removeByTarget(id, AlarmTargetCatalog.VENDOR.name());
                    ipPoolRepository.removeByVid(id, context.getTarget());
                    pbmProfileRepository.removeByVendorId(id);
                    lunRepository.removeByVendorId(id);
                    ipPoolPortGroupRepository.deleteByVendorId(id);
                    break;
                case KUBERNETES:
                    namespaceRepository.removeByVendor(id, context.getTarget());
                    nodeRepository.removeByVendor(id, context.getTarget());
                    serviceRepository.removeByVendor(id, context.getTarget());
                    podRepository.removeByVendor(id, context.getTarget());
                    kubeDeploymentRepository.removeByVendor(id, context.getTarget());
                    persistentVolumeRepository.removeByVendor(id, context.getTarget());
                    kubeContainerRepository.removeByVendor(id, context.getTarget());
                    kubeDaemonSetRepository.removeByVendor(id, context.getTarget());
                    kubeNodeLabelRepository.removeByVendor(id, context.getTarget());
                    kubePersistentVolumeClaimRepository.removeByVendor(id, context.getTarget());
                    kubeSecretRepository.removeByVendor(id, context.getTarget());
                    break;
                case H3C:
                    vdcRepository.removeByVendor(id, context.getTarget());
                    clusterRepository.removeByVendor(id, context.getTarget());
                    serverRepository.removeByVendor(id, context.getTarget());
                    dataStoreRepository.removeByVendor(id, context.getTarget());
                    storeHostRepository.removeByVendor(id);
                    snapshotRepository.removeByVid(id, context.getTarget());
                    networkCardRepository.removeByVid(id, context.getTarget());
                    switcherRepository.removeByVid(id, context.getTarget());
                    networkHostRepository.removeByVendor(id);
                    resourceRepository.removeByVid(id, context.getTarget());
                    ipRepository.deleteByVid(id);
                    dataStoreFileRepository.removeByVendor(id, context.getTarget());
                    ipPoolRepository.removeByVid(id, context.getTarget());
                    break;
                case POWERVC:
                    authDriver.removeAuthFromMemory(vendor.getUuid(), authentication.getString("address"),
                            authentication.getString("account"));

                    List<Server> serverList = serverRepository.listByVendor(id);
                    for (Server server : serverList) {
                        serverConfigRepository.removeBySid(server.getId());
                    }
                    powervcHmcRepository.removeByVendor(id, context.getTarget());
                    serverRepository.removeByVendor(id, context.getTarget());
                    hostSeaRepository.removeByVendor(id);
                    cloudServerRepository.removeByVid(id, context.getTarget());
                    serverVolumeRepository.removeByVendorid(id, context.getTarget());
                    storageRepository.removeByVendor(id);
                    sanFabricRepository.removeByVendor(id);
                    volumeTemplateRepository.removeByVendor(id);
                    volumeRepository.removeByVid(id, context.getTarget());
                    networkRepository.removeByVid(id, context.getTarget());
                    networkSeaRepository.deleteByVendorId(id);
                    subnetRepository.removeByVid(id, context.getTarget());
                    imageRepository.removeByVid(id, context.getTarget());
                    flavorRepository.removeByVid(id);
                    ipPoolRepository.removeByVid(id, context.getTarget());
                    ipRepository.deleteByVid(id);
                    portRepository.removeByVid(id, context.getTarget());
                    portFixedIpRepository.deleteByVendorId(id);
                    flavorExtraSpecsRepository.removeByVendorId(id);
                    clusterRepository.removeByVendor(id, context.getTarget());
                    volumePoolRepository.removeByVendor(id);
                    imageVolumeRepository.removeByVendorId(id, context.getTarget());
                    resourceRepository.removeByVid(id, context.getTarget());
                    break;
                case F5:
                    // 删除f5平台时加入对租户是否有在使用当前平台资源的检验
                    int projectCount = f5BiVirtualServerRepository.existsProject(id);
                    if (0 < projectCount) {
                        return new BocloudResult<>(false, "当前平台下存在租户正在使用的资源，请检查!");
                    }
                    f5BiPoolMemberRepository.removeByVId(id, context.getTarget());
                    f5BiPoolRepository.removeByVID(id, context.getTarget());
                    f5BiMonitorRepository.removeByVendor(id, context.getTarget());
                    f5BiNodeRepository.removeByVendor(id, context.getTarget());
                    f5BiProfileRepository.removeByVendor(id, context.getTarget());
                    f5BiVirtualServerRepository.removeByVendor(id, context.getTarget());
                    f5BiDnsResolversRepository.removeByVendor(id, context.getTarget());
                    f5BiIRulesRepository.removeByVendor(id, context.getTarget());
                    f5BiSnatPoolRepository.removeByVendor(id, context.getTarget());
                    f5BiTunnelRepository.removeByVendor(id, context.getTarget());
                    f5BiVlanRepository.removeByVendor(id, context.getTarget());
                    break;
                case TENCENT:
                case TCE:
                case QCLOUD:
                case PQCLOUD:
                case KINGCLOUD:
                case JDCLOUD:
                case ALIYUN:
                case HUAWEI:
                case HCSO:
                case AWS:
                case VOLCENGINE:
                case AZURE:
                case TIANYI:
                    List<CloudServer> awsServers = cloudServerRepository.listByVendorId(id);
                    if (null != awsServers && awsServers.size() > 0) {
                        for (CloudServer cloudServer : awsServers) {
                            serverKeypairRepository.removeBySid(cloudServer.getId());
                            serverSgroupRepository.removeBySid(cloudServer.getId());
                        }
                    }
                    tagRepository.removeByVid(id);
                    resourceGroupRepository.removeByVid(id, context.getTarget());
                    loadBalancerRepository.removeByVid(id, context.getTarget());
                    lbListenerRepository.removeByVid(id, context.getTarget());
                    internetGatewayRepository.removeByVid(id, context.getTarget());
                    elasticIpRepository.removeByVid(id, context.getTarget());
                    tagRepository.removeByVid(id);
                    zoneRepository.deleteByVid(id);
                    regionRepository.deleteByVid(id);
                    subnetRepository.removeByVid(id, context.getTarget());
                    cloudServerRepository.removeByVid(id, context.getTarget());
                    imageRepository.removeByVid(id, context.getTarget());
                    flavorRepository.removeByVid(id);
                    volumeRepository.removeByVid(id, context.getTarget());
                    snapshotRepository.removeByVid(id, context.getTarget());
                    securityGroupRepository.removeByVid(id, context.getTarget());
                    securityGroupRuleRepository.removeByVid(id, context.getTarget());
                    vpcRepository.deleteByVid(id, context.getTarget());
                    KeypairRepository.removeByVid(id, context.getTarget());
                    resourceRepository.removeByVid(id, context.getTarget());
                    networkInterfaceRepository.deleteByVid(id, context.getTarget());
                    routerRepository.removeByVid(id, context.getTarget());
                    routeTableRepository.removeByVid(id, context.getTarget());
                    routeRepository.removeByVid(id, context.getTarget());
                    natGatewayRepository.removeByVid(id, context.getTarget());
                    natGatewaySnatRuleRepository.removeByVid(id, context.getTarget());
                    natGatewayDnatRuleRepository.removeByVid(id, context.getTarget());
                    cidrBlockRepository.removeByVid(id, context.getTarget());
                    lbMemberRepository.removeByVid(id, context.getTarget());
                    lbPoolRepository.removeByVid(id, context.getTarget());
                    ipRepository.deleteByVid(id);
                    poolGroupZoneRepository.deleteByVid(id);
                    networkCardRepository.removeByVid(id, context.getTarget());
                    // 删除外部账单
                    cloudBillRepository.removeByVid(id);
                    List<Port> oPorts = portRepository.listByVid(id);
                    for (Port port : oPorts) {
                        portFixedIpRepository.deleteByPortId(port.getId());
                    }
                    portRepository.removeByVid(id, context.getTarget());
                    networkRepository.removeByVid(id, context.getTarget());
                    serverRepository.removeByVendor(id, context.getTarget());
                    tenantNetworkRepository.deleteByVendor(id);
                    ipPoolRepository.removeByVid(id, context.getTarget());
                    batchAccountRepository.removeByVid(id, context.getTarget());
                    storageAccountRepository.removeByVid(id, context.getTarget());
                    floatingIpRepository.removeByVid(id, context.getTarget());
                    backupVaultsRepository.removeByVid(id, context.getTarget());
                    backupRepository.removeByVid(id, context.getTarget());
                    break;
                case HMC:
                    hmcDatabaseHelper.removeHmcVendor(id, context.getTarget());
                    resourceRepository.removeByVid(id, context.getTarget());
                    // 删除CMP server中的数据
                    serverRepository.removeByVendor(id, context.getTarget());
                    String sessionClearUrl = "/v1/vendors/" + id + "/sessions";
                    Map<String, Object> headers = Collections.singletonMap(BocloudToken.INTERNAL_TOKEN, currentService.getToken());
                    List<RemoteService> remoteServices = serviceFactory.buildAll(BoCloudService.IMS, sessionClearUrl, BoCloudMethod.DELETE, headers, null);
                    for (RemoteService remoteService : remoteServices) {
                        taskExecutor.execute(remoteService::invoke);
                    }
                    break;
                case HORIZON:
                    desktopPoolRepository.removeByVendorId(id, context.getTarget());
                    sessionRepository.removeByVendorId(id, context.getTarget());
                    userOrGroupRepository.removeByVendorId(id, context.getTarget());
                    vcenterRepository.removeByVendorId(id, context.getTarget());
                    farmRepository.removeByVendorId(id, context.getTarget());
                    vcenterRelationRepository.removeByHorizonVendorId(id);
                    break;
                case SMARTX:
                    smartTransporter.remove(vendor, context.getTarget());
                    break;
                case FUSIONSPHERE:
                    vdcRepository.removeByVendor(id, context.getTarget());
                    osVersionRepository.deleteByVendorId(id);
                    clusterRepository.removeByVendor(id, context.getTarget());
                    List<Server> fuHosts = serverRepository.listByVendor(id);
                    for (Server server : fuHosts) {
                        serverConfigRepository.removeBySid(server.getId());
                    }
                    hostPortRepository.removeByVendorId(id, context.getTarget());
                    serverRepository.removeByVendor(id, context.getTarget());
                    //存储
                    List<FusionSphereStorageDevice> fusionSphereStorageDevices = storageDeviceRepository.listByVendor(id);
                    for (FusionSphereStorageDevice storageDevice : fusionSphereStorageDevices) {
                        deviceHostRepository.removeByDeviceId(storageDevice.getId());
                    }
                    storageDeviceRepository.removeByVendor(id, context.getTarget());
                    List<DataStore> stores = dataStoreRepository.listByVendor(id);
                    for (DataStore dataStore : stores) {
                        poolGroupRelationRepository.removeByTarget(dataStore.getId(), "Storage");
                    }
                    dataStoreRepository.removeByVendor(id, context.getTarget());
                    storeHostRepository.removeByVendor(id);
                    volumeRepository.removeByVid(id, context.getTarget());
                    //网络
                    List<Switcher> switchers = switcherRepository.listByVid(id);
                    switcherRepository.removeByVid(id, context.getTarget());
                    portGroupRepository.removeByVid(id, context.getTarget());
                    switchers.stream().forEach(
                            switcher -> {
                                upLinkRepository.deleteBySwitcherId(switcher.getId());
                                upLinkPortRepository.deleteBySwitcherId(switcher.getId());
                                vlanPoolRepository.deleteBySwitcherId(switcher.getId());
                            }
                    );
                    securityGroupRepository.removeByVid(id, context.getTarget());
                    securityGroupRuleRepository.removeByVid(id, context.getTarget());
                    //云主机
                    cloudServerRepository.removeByVid(id, context.getTarget());
                    resourceRepository.removeByVid(id, context.getTarget());
                    snapshotRepository.removeByVid(id, context.getTarget());
                    List<PoolGroup> poolGroups = poolGroupRepository.listByVendorId(id);
                    poolGroupRepository.removeByVid(id, context.getTarget());
                    poolGroups.stream().forEach(
                            poolGroup -> {
                                poolGroupRelationRepository.removeByPoolGroupId(poolGroup.getId());
                                portGroupRelationRepository.remove(poolGroup.getId());
                            }
                    );
                    break;
                default:
                    syncOrchestrator.removeVendor(id, context);
                    break;
            }
            if (!ListTool.isEmpty(servers)) {
                for (CloudServer cloudServer : servers) {
                    serverKeypairRepository.removeBySid(cloudServer.getId());
                    serverSgroupRepository.removeBySid(cloudServer.getId());
                    // 删除云主机的定时快照任务
                    snapshotTaskService.removeByVmId(cloudServer.getId());
                }
            }
            // 取消平台定时同步
            cloudVendorTaskService.remove(id, context);
            poolGroupRepository.removeByVid(id, context.getTarget());
            // 删除云主机
            cloudServerRepository.removeByVid(id, context.getTarget());
            ipRepository.deleteByVid(id);
            result = cloudVendorRepository.delete(id, context.getTarget());
            cosInternalService.deleteByVendor(id);
            cloudVendorStatisticsRepository.deleteByVendorId(id);
            // 在zk注册信息
            List<CloudVendor> cloudVendors = cloudVendorRepository.listAll();
            providerRegister.updateProvider(cloudVendors);
            for (CloudServer server : servers) {
                JSONObject object = new JSONObject();
                object.put("type", CloudServer.class.getSimpleName());
                object.put("data", server);
                amqpTemplate.convertAndSend("cmp.resource.deleted.queue", object);
            }
            for (Server host : hosts) {
                JSONObject object = new JSONObject();
                object.put("type", Server.class.getSimpleName());
                object.put("data", host);
                amqpTemplate.convertAndSend("cmp.resource.deleted.queue", object);
            }
            //删除成功后通知主机资源
            resourceTaskNotice.sendPhysicalDeleteMessage(id);
            resourceTaskNotice.sendLogicalDeleteMessage(id);
        } catch (Exception e) {
            logger.error("remove cloudVendor fail:", e);
            return new BocloudResult<>(false, "删除失败:" + e.getMessage());
        }
        return result ? new BocloudResult<>(true, "删除成功") : new BocloudResult<>(false, "删除失败");
    }

    @Override
    public BocloudResult lock(Long id, Long userId) {
        String path = CloudVendor.class.getSimpleName() + "_" + id;
        boolean result;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudVendor vendor = cloudVendorRepository.query(id);
            Assert.notNull(vendor, "数据不存在");
            result = cloudVendorRepository.lock(id, userId);
        } catch (Exception e) {
            logger.error("freeze cloudVendor fail:", e);
            return new BocloudResult<>(false, "冻结失败");
        }
        return result ? new BocloudResult<>(true, "冻结成功") : new BocloudResult<>(false, "冻结失败");
    }

    @Override
    public BocloudResult active(Long id, Long userId) {
        String path = CloudVendor.class.getSimpleName() + "_" + id;
        boolean result;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudVendor vendor = cloudVendorRepository.query(id);
            Assert.notNull(vendor, "数据不存在");
            result = cloudVendorRepository.active(id, userId);
        } catch (Exception e) {
            logger.error("freeze cloudVendor fail:", e);
            return new BocloudResult<>(false, "激活失败");
        }
        return result ? new BocloudResult<>(true, "激活成功") : new BocloudResult<>(false, "激活失败");
    }

    @Override
    public BocloudResult<CloudVendor> detail(Long id) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(id);
            Assert.notNull(vendor, "云平台不存在");
            String catalogIds = vendor.getCatalogIds();
            if (StringUtils.isEmpty(catalogIds)) {
                vendor.setCatalogIds("[]");
            } else {
                vendor.setCatalogIds("[" + catalogIds + "]");
            }
            return new BocloudResult<>(true, vendor, "查询详情成功");
        } catch (Exception e) {
            logger.error("query cloudVendor detail fail:", e);
            return new BocloudResult<>(false, "查询详情失败");
        }
    }

    @Override
    public BocloudResult checkName(String name) {
        try {
            CloudVendor vendor = cloudVendorRepository.getByName(name);
            return null == vendor ? new BocloudResult<>(true, "检查名称成功！") : new BocloudResult<>(false, "检查名称重复!");
        } catch (Exception e) {
            logger.error("get cloudVendor by name fail", e);
            return new BocloudResult<>(false, "检查名称失败!");
        }
    }

    /**
     * @since 2018-05-22 modify by sxp 支持hmc平台信息的查询
     */
    @Override
    public BocloudResult<GridBean<CloudVendor>> list(Pager pager, RequestContext context) {
        try {
            List<Param> params = Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>());
            Map<String, String> sorter = Optional.ofNullable(pager.getSorter()).orElse(Maps.newHashMap());
            Boolean simple = Optional.ofNullable(pager.getSimple()).orElse(false);
            sorter.put("priority", Common.ONE);
            Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
            Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);
            List<CloudVendor> list;
            List<SimpleBean> beans;
            int total;
            GridBean gridBean;
            total = cloudVendorRepository.count(params);
            if (simple) {
                beans = this.cloudVendorRepository.list(params, sorter);
                gridBean = new GridBean(1, 1, total, beans);
            } else {
                list = cloudVendorRepository.list(page, rows, params, sorter);
                gridBean = GridHelper.getBean(page, rows, total, list);
            }
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("list cloudVendor fail:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    private BocloudResult<List<CloudVendor>> listAllVendors() {
        try {
            List<Param> params = new ArrayList<>();
            return new BocloudResult<>(true, cloudVendorRepository.list(params), "查询成功！");
        } catch (Exception e) {
            logger.error("查询全部云平台异常：" + e.getMessage());
            return new BocloudResult<>(false, "查询全部云平台异常：" + e.getMessage());
        }
    }

    /**
     * 查询项目所在业务组中的云平台列表
     *
     * @param types
     * @param context
     * @return
     */
    public BocloudResult poolProviders(List<String> types, RequestContext context) {
        try {
            Long tenantId = context.getTenant();
            List<TenantPool> tenantPools = smsTenantService.listPoolByTenant(tenantId);
            Map<Long, CloudVendor> vendorMap = Maps.newHashMap();
            for (TenantPool pool : tenantPools) {
                PoolGroup poolGroup = poolGroupRepository.query(pool.getPoolGroupId());
                if (null != poolGroup) {
                    CloudVendor vendor = cloudVendorRepository.query(poolGroup.getVendorId());
                    if (null != vendor && !ListTool.isEmpty(types) && types.contains(vendor.getType())) {
                        vendorMap.put(vendor.getId(), vendor);
                    }
                }
            }
            return new BocloudResult<>(true, vendorMap.values(), "查询成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public List<CloudVendor> list(String type) {
        try {
            List<Param> params = Lists.newArrayList();
            params.add(new Param(MapTools.simpleMap("type", type), Sign.EQ));
            return cloudVendorRepository.list(1, Integer.MAX_VALUE, params, null, null);
        } catch (Exception e) {
            logger.error("list cloudVendor fail:", e);
            return Lists.newArrayList();
        }
    }

    @Override
    public List<CloudVendor> listAll() {
        try {
            return cloudVendorRepository.listAll();
        } catch (Exception e) {
            logger.error("list cloudVendor fail:", e);
            return Lists.newArrayList();
        }
    }

    @Override
    public BocloudResult listAuthProvider(List<String> types, Long tenantId) {
        try {
            List<CloudVendor> vendors = cloudVendorRepository.listAuthProvider(types, tenantId);
            return new BocloudResult<>(true, vendors, "查询成功");
        } catch (Exception e) {
            logger.error("list cloudVendor fail:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult createAlarm(AlarmThreshold alarmThreshold) {
        String path = CloudVendor.class.getSimpleName() + "_" + alarmThreshold.getTarget();
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            if ("SCP".equalsIgnoreCase(alarmThreshold.getCatalog())) {
                AlarmThreshold oldThreshold = alarmThresholdRepository.getByTarget(alarmThreshold.getTarget(),
                        AlarmTargetCatalog.SCP.name(), alarmThreshold.getSerialNumber());
                if (null == oldThreshold) {
                    alarmThreshold.setCatalog(AlarmTargetCatalog.SCP.name());
                    alarmThresholdRepository.create(alarmThreshold);
                    return new BocloudResult<>(true, "平台告警阈值设置成功");
                } else {
                    oldThreshold.setDiskYellowVal(alarmThreshold.getDiskYellowVal());
                    oldThreshold.setDiskRedVal(alarmThreshold.getDiskRedVal());
                    boolean flag = alarmThresholdRepository.update(oldThreshold);
                    if (!flag) {
                        return new BocloudResult<>(false, "平台告警阈值更新失败");
                    }
                    return new BocloudResult<>(true, "平台告警阈值更新成功");
                }
            }
            AlarmThreshold oldThreshold = alarmThresholdRepository.getByTarget(alarmThreshold.getTarget(),
                    AlarmTargetCatalog.VENDOR.name());
            if (null == oldThreshold) {
                alarmThreshold.setCatalog(AlarmTargetCatalog.VENDOR.name());
                alarmThresholdRepository.create(alarmThreshold);
                return new BocloudResult<>(true, "平台告警阈值设置成功");
            } else {
                oldThreshold.setCpuYellowVal(alarmThreshold.getCpuYellowVal());
                oldThreshold.setCpuRedVal(alarmThreshold.getCpuRedVal());
                oldThreshold.setMemoryYellowVal(alarmThreshold.getMemoryYellowVal());
                oldThreshold.setMemoryRedVal(alarmThreshold.getMemoryRedVal());
                boolean flag = alarmThresholdRepository.update(oldThreshold);
                if (!flag) {
                    return new BocloudResult<>(false, "平台告警阈值更新失败");
                }
                return new BocloudResult<>(true, "平台告警阈值更新成功");
            }
        } catch (Exception e) {
            logger.error("Vendor Alarm threshold setting failed", e);
            return new BocloudResult<>(false, "平台告警阈值设置失败");
        }
    }

    @Override
    public BocloudResult<AlarmThreshold> getAlarm(Long target) {
        try {
            AlarmThreshold alarmThreshold = alarmThresholdRepository.getByTarget(target,
                    AlarmTargetCatalog.VENDOR.name());
            if (null == alarmThreshold) {
                alarmThreshold = alarmThresholdRepository.getByTarget(target, AlarmTargetCatalog.SCP.name());
            }
            if (null == alarmThreshold) {
                alarmThreshold = new AlarmThreshold();
            }
            return new BocloudResult<>(true, alarmThreshold, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    /**
     * 查看vcenter平台全部集群的内存/cpu/存储的总使用量
     * <p>
     * 注：不在集群中的主机不统计
     * </p>
     *
     * @param id 平台唯一标识
     * @author sxp
     * @since Apr 23, 2018
     * @since 2018-04-25 modify by sxp 与ClusterServiceImpl.list统计数据逻辑保持一致
     * @since 2018-04-26 modify by sxp 优先使用实时数据
     * @since 2018-04-26 modify by sxp 删除使用实时数据的代码
     * @since 2018-05-18 modify by sxp 磁盘容量求和之后四舍五入保留两位小数
     */
    @Override
    public BocloudResult<CloudVendor> queryCapacity(Long id) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(id);
            if (vendor == null) {
                return new BocloudResult<>(false, "系统中不存在唯一标识为[" + id + "]的平台信息");
            }
            List<Cluster> clusters = clusterRepository.listByVendor(id);
            Long cpuTotal = 0L;
            Double diskTotal = 0D, diskUsed = 0D, memTotal = 0D, memUsed = 0D;
            Integer cpuUsed = 0, vmCpu, vmCpuNum, serverCpuNum;
            ServerConfig serverConfig;
            List<Param> params = new ArrayList<>(1);
            List<SimpleBean> hosts;
            List<CloudServer> vms;
            List<DataStore> stores = dataStoreRepository.listByVendor(id);
            Map<String, DataStore> storeMap = new HashMap<>();
            for (DataStore store : stores) {
                storeMap.put(store.getName() + store.getStoreVal(), store);
            }
            for (DataStore store : storeMap.values()) {
                if (null == store.getCapacity()) {
                    store.setCapacity(0L);
                }
                if (null == store.getFreeSpace()) {
                    store.setFreeSpace(0L);
                }
                diskTotal += store.getCapacity();
                diskUsed += (store.getCapacity() - store.getFreeSpace());
            }
            for (Cluster cluster : clusters) {
                params.clear();
                params.add(new Param(MapTools.simpleMap("clusterId", cluster.getId()), Sign.EQ));
                hosts = serverRepository.list(params, null, null);
                for (SimpleBean host : hosts) {
                    // 根据宿主机统计总量
                    serverConfig = serverConfigRepository.getBySid(host.getId());
                    if (serverConfig != null) {
                        cpuTotal += serverConfig.getCpuHz();
                        memTotal += serverConfig.getMemoryCapacity();
                    }
                    // 根据云主机分配额来统计使用量
                    vms = cloudServerRepository.listByHid(host.getId());
                    for (CloudServer vm : vms) {
                        // diskUsed += null == vm.getDisk() ? 0 : vm.getDisk();
                        if (vm.getIsTemplate()) {
                            continue;
                        }
                        if (serverConfig != null) {
                            vmCpuNum = vm.getCpu();
                            if (vmCpuNum == null) {
                                vmCpuNum = 0;
                            }
                            serverCpuNum = serverConfig.getCpuCore();
                            vmCpu = (int) ((double) vmCpuNum / serverCpuNum * serverConfig.getCpuHz());
                            cpuUsed += vmCpu;
                        }
                        memUsed += null == vm.getMemory() ? 0 : vm.getMemory().doubleValue();
                    }
                }
            }
            // 查询集群外的宿主机
            List<Server> aloneHosts = serverRepository.listByVendor(id);
            for (Server host : aloneHosts) {
                if (null == host.getClusterId() || 0L == host.getClusterId()) {
                    // 根据宿主机统计总量
                    serverConfig = serverConfigRepository.getBySid(host.getId());
                    if (serverConfig != null) {
                        cpuTotal += serverConfig.getCpuHz();
                        memTotal += serverConfig.getMemoryCapacity();
                    }
                    // 根据云主机分配额来统计使用量
                    vms = cloudServerRepository.listByHid(host.getId());
                    for (CloudServer vm : vms) {
                        diskUsed += null == vm.getDisk() ? 0 : vm.getDisk();
                        if (vm.getIsTemplate()) {
                            continue;
                        }
                        if (serverConfig != null) {
                            vmCpuNum = vm.getCpu();
                            if (vmCpuNum == null) {
                                vmCpuNum = 0;
                            }
                            serverCpuNum = serverConfig.getCpuCore();
                            vmCpu = (int) ((double) vmCpuNum / serverCpuNum * serverConfig.getCpuHz());
                            cpuUsed += vmCpu;
                        }
                        memUsed += null == vm.getMemory() ? 0 : vm.getMemory().doubleValue();
                    }
                }
            }
            diskTotal = MathUtils.round(diskTotal, 2);
            diskUsed = MathUtils.round(diskUsed, 2);
            vendor.setCpuTotal(cpuTotal);
            vendor.setCpuUsed(Long.valueOf(cpuUsed));
            vendor.setCpuUnused(cpuTotal - cpuUsed);
            vendor.setMemTotal(BigDecimal.valueOf(memTotal).setScale(2, BigDecimal.ROUND_HALF_UP));
            vendor.setMemUsed(BigDecimal.valueOf(memUsed).setScale(2, BigDecimal.ROUND_HALF_UP));
            vendor.setMemUnused(BigDecimal.valueOf(memTotal - memUsed).setScale(2, BigDecimal.ROUND_HALF_UP));
            vendor.setDiskTotal(BigDecimal.valueOf(diskTotal).setScale(2, BigDecimal.ROUND_HALF_UP));
            vendor.setDiskUsed(BigDecimal.valueOf(diskUsed).setScale(2, BigDecimal.ROUND_HALF_UP));
            vendor.setDiskUnused(BigDecimal.valueOf(diskTotal - diskUsed).setScale(2, BigDecimal.ROUND_HALF_UP));
            JSONObject authentication = JSONObject.parseObject(vendor.getAuthentication());
            // 敏感数据消密
            if (null != authentication) {
                authentication.put("account", "***");
                authentication.put(Constant.KEY, "***");
                vendor.setAuthentication(JSONObject.toJSONString(authentication));
            }
            return new BocloudResult<>(true, vendor, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    /**
     * 根据平台类型查询所有平台
     *
     * @param type
     * @return
     */
    @Override
    public BocloudResult getByType(String type) {
        try {
            List<CloudVendor> cloudVendors = cloudVendorRepository.listByType(type);
            return new BocloudResult<>(true, cloudVendors, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult listByPool(String params) {
        try {
            JSONObject parseObject = JSONObject.parseObject(params, JSONObject.class);
            String category = parseObject.getString("category");
            if (null == category) {
                return new BocloudResult<>(false, "参数格式有误！");
            }
            Boolean isPublic = null;
            if (parseObject.containsKey("isPublic")) {
                isPublic = parseObject.getBoolean("isPublic");
            }
            List<CloudVendor> cloudVendors = cloudVendorRepository.listByPool(category, isPublic);
            return new BocloudResult<>(true, cloudVendors, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult batchOpenAlarm(List<Long> ids, Long userId) {
        if (null == ids) {
            return ResultTools.formatErrResult();
        }
        try {
            List<CloudVendor> succIds = Lists.newArrayList();
            int succResult = 0;
            int failResult = 0;
            for (Long id : ids) {
                CloudVendor cloudVendor = cloudVendorRepository.query(id);
                cloudVendor.setIsAlarm(true);
                cloudVendor.setGmtModify(new Date());
                cloudVendor.setMenderId(userId);
                boolean result = cloudVendorRepository.update(cloudVendor);
                if (result) {
                    succIds.add(cloudVendor);
                    succResult++;
                } else {
                    failResult++;
                }
            }
            return new BocloudResult<>(true, succIds, "批量开启告警成功【" + succResult + "】个，失败【" + failResult + "】个");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "批量开启告警失败");
        }
    }

    @Override
    public BocloudResult batchCloseAlarm(List<Long> ids, Long userId) {
        if (ListTool.isEmpty(ids)) {
            return new BocloudResult<>(false, "参数格式错误");
        }
        try {
            List<CloudVendor> succIds = Lists.newArrayList();
            int succResult = 0;
            int failResult = 0;
            for (Long id : ids) {
                CloudVendor cloudVendor = cloudVendorRepository.query(id);
                cloudVendor.setIsAlarm(false);
                cloudVendor.setGmtModify(new Date());
                cloudVendor.setMenderId(userId);
                boolean result = cloudVendorRepository.update(cloudVendor);
                if (result) {
                    succIds.add(cloudVendor);
                    succResult++;
                } else {
                    failResult++;
                }
            }
            return new BocloudResult<>(true, succIds, "批量关闭告警成功【" + succResult + "】个，失败【" + failResult + "】个");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "批量关闭告警失败");
        }
    }

    @Override
    public BocloudResult batchOperationAlarm(List<Long> ids, String action, Long userId) {
        if ("open".equalsIgnoreCase(action)) {
            return this.batchOpenAlarm(ids, userId);
        } else {
            return this.batchCloseAlarm(ids, userId);
        }
    }

    /**
     * 根据平台类型查询
     *
     * @param types
     * @return
     */
    @Override
    public BocloudResult listByTypes(List<String> types) {
        try {
            List<CloudVendor> vendors = cloudVendorRepository.listByTypes(types, null);
            return new BocloudResult<>(true, vendors, "查询成功");
        } catch (Exception e) {
            logger.error("list cloudVendor fail:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    private BocloudResult listByTypes(JSONObject object) {
        try {
            List<String> vendorTypes = JSONArray.parseArray(object.getString("vendorTypes"), String.class);
            Long dcId = object.getLong("dcId");
            List<CloudVendor> vendors = cloudVendorRepository.listByTypes(vendorTypes, dcId);
            return new BocloudResult<>(true, vendors, "查询成功");
        } catch (Exception e) {
            logger.error("list cloudVendor fail:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    public BocloudResult listSimpleTypes(List<String> types) {
        try {
            List<CloudVendor> vendors = cloudVendorRepository.listSimpleTypes(types);
            return new BocloudResult<>(true, vendors, "查询成功");
        } catch (Exception e) {
            logger.error("list cloudVendor fail:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }


    /**
     * 云平台操作
     *
     * @param id
     * @param action
     * @param context
     * @return
     */
    @Override
    public BocloudResult action(Long id, String action, RequestContext context) {
        switch (action) {
            case "active":
                return active(id, context.getTarget());
            case "lock":
                return lock(id, context.getTarget());
            default:
                return new BocloudResult<>(false, "暂不支持");
        }
    }

    @Override
    public BocloudResult updatePassword(Long id, CloudVendor cloudVendor, RequestContext context) {
        CloudVendor vendor = cloudVendorRepository.query(id);
        if (null == vendor) {
            return new BocloudResult(false, "云平台不存在");
        }
        JSONObject oldAuthentication = null;
        JSONObject callbackAuthentication = null;
        String path = CloudVendor.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            Assert.notNull(cloudVendor, "参数格式错误");
            Encryptor encryptor = new AESEncrptor();
            String oldPassword = cloudVendor.getOldPassword();
            String newPassword = cloudVendor.getNewPassword();
            oldAuthentication = JSONObject.parseObject(vendor.getAuthentication());
            callbackAuthentication = JSONObject.parseObject(vendor.getAuthentication());
            String updatePswdType = null;
            if (!StringUtils.isEmpty(oldPassword) && !StringUtils.isEmpty(newPassword)) {
                oldPassword = encryptor.decrypt(oldPassword, null);
                newPassword = encryptor.decrypt(newPassword, null);
                if (oldAuthentication.containsKey("password")) {
                    encryptor = new DESEncrptor();
                    String password = encryptor.decrypt(oldAuthentication.getString("password").trim(), "BocloudCMP");
                    if (!password.equalsIgnoreCase(oldPassword)) {
                        return new BocloudResult<>(false, "原密码错误");
                    }
                    oldAuthentication.put("password", encryptor.encrypt(newPassword, "BocloudCMP"));
                    updatePswdType = "password";
                }
            } else {
                if (CloudProvider.AZURE.name().equals(vendor.getType())) {
                    encryptor = new AESEncrptor();
                    String secretKey = encryptor.decrypt(cloudVendor.getSecretKey().trim(), null);
                    encryptor = new DESEncrptor();
                    secretKey = encryptor.encrypt(secretKey, "BocloudCMP");
                    oldAuthentication.put("clientId", cloudVendor.getClientId());
                    oldAuthentication.put("secretKey", secretKey);
                    updatePswdType = "azure";
                } else {
                    encryptor = new AESEncrptor();
                    String accessKey = encryptor.decrypt(cloudVendor.getAccessKey().trim(), null);
                    String secretKey = encryptor.decrypt(cloudVendor.getSecretKey().trim(), null);
                    encryptor = new DESEncrptor();
                    accessKey = encryptor.encrypt(accessKey, "BocloudCMP");
                    secretKey = encryptor.encrypt(secretKey, "BocloudCMP");
                    oldAuthentication.put("accessKey", accessKey);
                    oldAuthentication.put("secretKey", secretKey);
                    updatePswdType = "aksk";
                }
            }
            vendor.setAuthentication(oldAuthentication.toJSONString());
            vendor.setMenderId(context.getTarget());
            cloudVendorRepository.update(vendor);
            // 在zk注册信息
            List<CloudVendor> list = cloudVendorRepository.listAll();
            this.providerRegister.updateProvider(list);
            boolean cacheStatus = waitUpdateProviderCache(vendor, updatePswdType);
            Assert.isTrue(cacheStatus, "缓存更新刷新失败！");
            //校验密码是否正确
            BocloudResult result = authDriver.auth(vendor.getUuid(), null);
            Assert.isTrue(result.isSuccess(), "云平台认证失败！");
            return new BocloudResult<>(true, "密码更新成功");
        } catch (Exception e) {
            if (null != callbackAuthentication) {
                vendor.setAuthentication(callbackAuthentication.toJSONString());
            }
            vendor.setMenderId(context.getTarget());
            cloudVendorRepository.update(vendor);
            logger.error("Get error message:{}", e.getMessage());
            return new BocloudResult<>(false, e.getMessage());
        }
    }


    private boolean waitUpdateProviderCache(CloudVendor vendor, String type) throws Exception {
        boolean flag = false;
        Encryptor encryptor = new DESEncrptor();
        JSONObject authentication = JSONObject.parseObject(vendor.getAuthentication());
        Long startTime = System.currentTimeMillis();
        Long endTime = System.currentTimeMillis();
        while (endTime - startTime < 3 * 1000) {
            Thread.sleep(500);
            Butler butler = ButlerRepository.getInstance().get(vendor.getUuid());
            if (type.equalsIgnoreCase("password")) {
                String vendorPassword = authentication.getString("password");
                String butlerPassword = encryptor.encrypt(butler.getPassword(), "BocloudCMP");
                if (vendorPassword.equalsIgnoreCase(butlerPassword)) {
                    flag = true;
                    break;
                }
            } else if (type.equalsIgnoreCase("aksk")) {
                String vendorAccessKey = authentication.getString("accessKey");
                String vendorSecretKey = authentication.getString("secretKey");
                String butlerAccessKey = encryptor.encrypt(butler.getAccessKey(), "BocloudCMP");
                String butlerSecretKey = encryptor.encrypt(butler.getSecretKey(), "BocloudCMP");
                if (vendorAccessKey.equalsIgnoreCase(butlerAccessKey) && vendorSecretKey.equalsIgnoreCase(butlerSecretKey)) {
                    flag = true;
                    break;
                }
            } else if (type.equalsIgnoreCase("azure")) {
                String vendorClientId = authentication.getString("clientId");
                String vendorSecretKey = authentication.getString("secretKey");
                String butlerClientId = butler.getClientId();
                String butlerSecretKey = encryptor.encrypt(butler.getSecretKey(), "BocloudCMP");
                if (vendorClientId.equalsIgnoreCase(butlerClientId) && vendorSecretKey.equalsIgnoreCase(butlerSecretKey)) {
                    flag = true;
                    break;
                }
            }
            endTime = System.currentTimeMillis();
        }
        return flag;
    }


    @Override
    public BocloudResult condition(String condition, RequestContext context) {
        try {
            condition = Optional.ofNullable(condition).orElse("");
            JSONObject object = JSONObject.parseObject(condition);
            if ("checkName".equalsIgnoreCase(object.getString("condition"))) {
                return this.checkName(object.getString("name"));
            } else if ("poolProviders".equalsIgnoreCase(object.getString("condition"))) {
                List<String> types = JSONArray.parseArray(object.getString("types"), String.class);
                if (null == types) {
                    return ResultTools.formatErrResult();
                }
                return this.poolProviders(types, context);
            } else if ("listByType".equalsIgnoreCase(object.getString("condition"))) {
                return this.getByType(object.getString("type"));
            } else if ("listByTypes".equalsIgnoreCase(object.getString("condition"))) {
                return listByTypes(JSONArray.parseArray(object.getString("types"), String.class));
            } else if ("listSimpleTypes".equalsIgnoreCase(object.getString("condition"))) {
                return listSimpleTypes(JSONArray.parseArray(object.getString("types"), String.class));
            } else if ("vendorTypes".equalsIgnoreCase(object.getString("condition"))) {
                return this.listByTypes(object);
            } else if ("listByPool".equalsIgnoreCase(object.getString("condition"))) {
                return this.listByPool(condition);
            } else if ("listAllVendors".equalsIgnoreCase(object.getString("condition"))) {
                return this.listAllVendors();
            } else if ("listByAz".equalsIgnoreCase(object.getString("condition"))) {
                CloudVendor vendor = cloudVendorRepository.getByRegion(object.getString("region"),
                        object.getString("zone"), CloudProvider.VMWARE.name());
                if (null == vendor) {
                    return new BocloudResult<>(false, "云平台不存在");
                }
                return new BocloudResult<>(true, vendor, "查询成功");
            } else if ("getNsxVendor".equalsIgnoreCase(object.getString("condition"))) {
                CloudVendor vendor = cloudVendorRepository.getNsxVendor(object.getString("region"),
                        object.getString("az"));
                if (null == vendor) {
                    return new BocloudResult<>(true, "查询成功");
                }
            } else if ("getVcVcenterByHorizon".equalsIgnoreCase(object.getString("condition"))) {
                List<VmwareHorizonVcenterRelation> relations = vcenterRelationRepository
                        .listByHorizonVendorId(object.getLong("vendorId"));
                List<Long> vcVendorIds = relations.stream().filter(relation -> null != relation.getVcenterVendorId())
                        .map(relation -> relation.getVcenterVendorId()).collect(Collectors.toList());
                List<CloudVendor> vendors = cloudVendorRepository.listByIds(vcVendorIds);
                return new BocloudResult<>(true, vendors, "查询成功");

            } else if ("listTypeByTenant".equalsIgnoreCase(object.getString("condition"))) {
                List<TenantPool> pools = smsTenantService.listPoolByTenant(context.getTenant());
                if (ListTool.isEmpty(pools)) {
                    return new BocloudResult<>(false, "当前租户未授权资源池！");
                }
                List<Long> ids = pools.stream().map(TenantPool::getPoolGroupId).collect(Collectors.toList());
                List<PoolGroup> listByIds = poolGroupRepository.listByIds(ids);
                List<Long> vendorIds = listByIds.stream().map(PoolGroup::getVendorId).collect(Collectors.toList());
                String types = object.getString("types");
                List<String> typeList = JSONObject.parseArray(types, String.class);
                List<CloudVendor> vendors = cloudVendorRepository.listByIds(vendorIds, typeList);
                Set<String> collect = vendors.stream().map(CloudVendor::getType).collect(Collectors.toSet());
                return new BocloudResult<>(true, collect, "查询成功");
            } else if ("listTypeByCatalogId".equals(object.getString("condition"))) {
                return this.listTypeByCatalogId(object.getLong("catalogId"));
            }
        } catch (Exception e) {
            logger.error("查询失败：" + e.getMessage());
        }
        return new BocloudResult<>(false, "参数格式错误");
    }

    private BocloudResult listTypeByCatalogId(Long catalogId) {
        try {
            ServiceCatalog catalog = cosInternalService.getServiceCatalog(catalogId);
            Map<String, Boolean> vendorMap = cloudVendorRepository.listAll().stream().collect(Collectors.toMap(CloudVendor::getType, CloudVendor::getIsPublic, (m1, m2) -> m2));
            BocloudResult<List<Dictionary>> typesData = smsDictionaryService.dictionaries("SERVICE_CATALOG");
            List<Dictionary> serviceDics = typesData.getData();
            List<Dictionary> types = new ArrayList<>();
            for (Dictionary dictionary : serviceDics) {
                if (dictionary.getValue().equalsIgnoreCase(catalog.getCode())) {
                    types = dictionary.getChildren();
                }
            }
            Map<String, Dictionary> vendorTypeMap = types.stream().collect(Collectors.toMap(Dictionary::getValue, Function.identity(), (m1, m2) -> m1));
            JSONArray result = new JSONArray();
            for (Map.Entry<String, Boolean> entry : vendorMap.entrySet()) {
                String type = entry.getKey();
                if (vendorTypeMap.containsKey(type)) {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("vendorType", type);
                    jsonObject.put("name", vendorTypeMap.get(type).getName());
                    jsonObject.put("public", entry.getValue());
                    result.add(jsonObject);
                }
            }
            return new BocloudResult<>(true, result, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "查询失败");
        }

    }

    @Override
    public BocloudResult clearSession(Long id, RequestContext context) {
        CloudVendor vendor = cloudVendorRepository.get(CloudVendor.class, id);
        Assert.notNull(vendor, "数据不存在");
        JSONObject authentication = JSONObject.parseObject(vendor.getAuthentication());
        String address = authentication.getString("address");
        String account = authentication.getString("account");
        authDriver.removeAuthFromMemory(vendor.getUuid(), address, account);
        return new BocloudResult(true, "执行成功");
    }

    @Override
    public BocloudResult updateExcessRatio(Long id, CloudVendor cloudVendor, RequestContext context) {
        String path = CloudVendor.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            Assert.notNull(cloudVendor, "参数格式错误");
            CloudVendor vendor = cloudVendorRepository.query(id);
            Assert.notNull(vendor, "云平台不存在");
            JSONObject authentication = JSONObject.parseObject(vendor.getAuthentication());
            authentication.put("excessRatio", cloudVendor.getExcessRatio());
            vendor.setAuthentication(authentication.toJSONString());
            vendor.setMenderId(context.getTarget());
            cloudVendorRepository.update(vendor);
            return new BocloudResult<>(true, "超分比更新成功");
        } catch (Exception e) {
            logger.error("超分比更新失败:{}", e.getMessage());
            return new BocloudResult<>(false, "超分比更新失败：" + e.getMessage());
        }
    }

    @Override
    public BocloudResult summary(Long id, RequestContext context) {
        CloudVendor vendor = cloudVendorRepository.query(id);
        Assert.notNull(vendor, "云平台不存在");
        if (CloudProvider.SMARTX.name().equals(vendor.getType())) {
            BocloudResult bocloudResult = locationDriver.summary(vendor.getUuid());
            Assert.isTrue(bocloudResult.isSuccess(), bocloudResult.getMessage());
            JSONObject object = JSON.parseObject(JSON.toJSONString(bocloudResult.getData()));

            long serverCnt = 0, hddCnt = 0, ssdCnt = 0, vmCnt = 0, volumeCnt = 0, vmTmplCnt = 0;
            long serverHealthyCnt = 0, serverUnhealthyCnt = 0;
            List<Server> servers = serverRepository.listByVendor(vendor.getId());
            for (Server server : servers) {
                ServerConfig serverConfig = serverConfigRepository.query(server.getId());
                hddCnt += serverConfig.getHddCount();
                ssdCnt += serverConfig.getSsdCount();
            }
            serverCnt = servers.size();
            serverHealthyCnt = servers.stream().filter(svr ->
                    BocloudStatus.Server.RUNNING.name().equals(svr.getStatus())).count();
            serverUnhealthyCnt = servers.stream().filter(svr ->
                    !BocloudStatus.Server.RUNNING.name().equals(svr.getStatus())).count();

            vmCnt = cloudServerRepository.listByVendorId(vendor.getId()).size();
            vmTmplCnt = cloudServerRepository.listTemplate(vendor.getId(), null).size();
            volumeCnt = volumeRepository.listByVendorId(vendor.getId()).size();

            Map<String, Object> count = MapBuilder.init()
                    .put("server", serverCnt)
                    .put("hdd", hddCnt)
                    .put("ssd", ssdCnt)
                    .put("vm", vmCnt)
                    .put("volume", volumeCnt)
                    .put("template", vmTmplCnt)
                    .get();

            Map<String, Object> server = MapBuilder.init()
                    .put("total", serverCnt)
                    .put("healthy", serverHealthyCnt)
                    .put("unhealthy", serverUnhealthyCnt)
                    .get();

            object.put("count", count);
            object.put("server", server);

            return new BocloudResult(true, object, "success");
        }
        return new BocloudResult(false, "该云平台暂不支持此操作");
    }

    @Override
    public BocloudResult updateBillFactor(Long id, CloudVendor cloudVendor, RequestContext context) {
        try {
            Assert.isTrue(cloudVendor.getBillFactor().intValue() >= 0, "账单系数不符合要求, 数值应为正数");
            CloudVendor vendor = cloudVendorRepository.query(id);
            Assert.notNull(vendor, "云平台不存在");
            boolean success = cloudVendorRepository.updateBillFactor(id, cloudVendor.getBillFactor());
            if (success) {
                return new BocloudResult(true, "更新公有云账单系数成功");
            }
        } catch (Exception e) {
            logger.error("更新公有云账单系数失败", e);
            return BocloudResult.FAILED("更新公有云账单系数失败：" + e.getMessage());
        }
        return BocloudResult.FAILED("更新公有云账单系数失败");
    }
}
