package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.common.AuthDriver;
import com.bocloud.cmp.driver.common.LocationDriver;
import com.bocloud.cmp.driver.f5.F5DeviceDriver;
import com.bocloud.cmp.driver.monitor.AlarmDriver;
import com.bocloud.cmp.driver.pbm.PbmProfileDriver;
import com.bocloud.cmp.driver.storage.StorageGatewayDriver;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.entity.enums.ModuleCode;
import com.bocloud.cmp.entity.enums.SyncType;
import com.bocloud.cmp.model.*;
import com.bocloud.cmp.model.contentlibrary.ItemModel;
import com.bocloud.cmp.model.contentlibrary.LibraryModel;
import com.bocloud.cmp.provider.ButlerRepository;
import com.bocloud.cmp.provider.VmwareProvider;
import com.bocloud.cmp.provider.utils.AssembleTools;
import com.bocloud.common.enums.BaseStatus;
import com.bocloud.common.enums.BoCloudService;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.OperateResult;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.IDFactory;
import com.bocloud.common.utils.ListTool;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.entity.common.Dictionary;
import com.bocloud.ims.entity.common.VendorSyncRecord;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.contentlibrary.ContentLibrary;
import com.bocloud.ims.entity.resource.contentlibrary.ContentLibraryItem;
import com.bocloud.ims.entity.resource.manageone.ManageOneAccount;
import com.bocloud.ims.interfaces.resource.CloudStackService;
import com.bocloud.ims.interfaces.resource.IpService;
import com.bocloud.ims.interfaces.resource.SyncService;
import com.bocloud.ims.interfaces.scheduler.SnapshotTaskService;
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.resource.*;
import com.bocloud.ims.repository.resource.contentlibrary.ContentLibraryItemRepository;
import com.bocloud.ims.repository.resource.contentlibrary.ContentLibraryRepository;
import com.bocloud.ims.repository.resource.f5.*;
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.model.cmdb.CmdbInfo;
import com.bocloud.ims.service.model.cmdb.CmdbModel;
import com.bocloud.ims.service.model.cmdb.CmdbRelation;
import com.bocloud.ims.service.thread.AlarmSyncTask;
import com.bocloud.ims.service.topology.InstanceMessageDispatcher;
import com.bocloud.ims.service.transportor.*;
import com.bocloud.ims.service.utils.*;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.bocloud.vmware.vim25.mo.Datacenter;
import com.bocloud.vmware.vim25.mo.InventoryNavigator;
import com.bocloud.vmware.vim25.mo.ManagedEntity;
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.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 同步云平台service接口实现类
 *
 * @author weiwei
 * @since 2017.02.27
 */
@Service("syncService")
public class SyncServiceImpl implements SyncService {

    private static final Logger logger = LoggerFactory.getLogger(SyncServiceImpl.class);
    @Autowired
    private TianyiTransportor tianyiTransportor;
    @Autowired
    private HmcTransportor hmcTransportor;
    @Autowired
    private HmdTransportor hmdTransportor;
    @Autowired
    private PowervcTransportor powervcTransportor;
    @Autowired
    private ServerRepository serverRepository;
    @Autowired
    private VdcRepository vdcRepository;
    @Autowired
    private ClusterRepository clusterRepository;
    @Autowired
    private DataStoreRepository dataStoreRepository;
    @Autowired
    private StoreHostRepository storeHostRepository;
    @Autowired
    private StorageGatewayRepository storageGatewayRepository;
    @Autowired
    private CloudServerRepository cloudServerRepository;
    @Autowired
    private StorageGatewayDriver storageGatewayDriver;
    @Autowired
    private SnapshotRepository snapshotRepository;
    @Autowired
    private NetworkRepository networkRepository;
    @Autowired
    private ServerConfigRepository serverConfigRepository;
    @Autowired
    private ServerAssetsRepository serverAssetsRepository;
    @Autowired
    private LocationDriver locationDriver;
    @Autowired
    private AuthDriver authDriver;
    @Autowired
    private AlarmDriver alarmDriver;
    @Autowired
    private ImageRepository imageRepository;
    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private ResourceAlarmRepository alarmRepository;
    @Autowired
    private NetworkCardRepository networkCardRepository;
    @Autowired
    private VolumeRepository volumeRepository;
    @Autowired
    private PortGroupRepository portGroupRepository;
    @Autowired
    private NetworkHostRepository networkHostRepository;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private ClusterNodeRepository clusterNodeRepository;
    @Autowired
    private ResourceRepository resourceRepository;
    @Autowired
    private IpRepository ipRepository;
    @Autowired
    private IpPoolRepository ipPoolRepository;
    @Autowired
    private SwitcherRepository switcherRepository;
    @Autowired
    private ResourcePoolRepository resourcePoolRepository;
    @Autowired
    private ServerLabelRepository serverLabelRepository;
    @Autowired
    private IpService ipService;
    @Autowired
    private SnapshotTaskRepository snapshotTaskRepository;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private SecurityGroupRepository securityGroupRepository;
    @Autowired
    private SecurityGroupRuleRepository securityGroupRuleRepository;
    @Autowired
    private ServerSgroupRepository serverSgroupRepository;
    @Autowired
    private ProviderRegister providerRegister;
    @Autowired
    private F5DeviceDriver f5DeviceDriver;
    @Autowired
    private F5BiNodeRepository f5BiNodeRepository;
    @Autowired
    private F5BiProfileRepository f5BiProfileRepository;
    @Autowired
    private F5BiMonitorRepository f5BiMonitorRepository;
    @Autowired
    private F5BiPoolRepository f5BiPoolRepository;
    @Autowired
    private F5BiPoolMemberRepository f5BiPoolMemberRepository;
    @Autowired
    private F5BiVirtualServerRepository f5BiVirtualServerRepository;
    @Autowired
    private F5BiIRulesRepository f5BiIRulesRepository;
    @Autowired
    private F5BiDnsResolversRepository f5BiDnsResolversRepository;
    @Autowired
    private F5BiSnatPoolRepository f5BiSnatPoolRepository;
    @Autowired
    private F5BiVlanRepository f5BiVlanRepository;
    @Autowired
    private F5BiTunnelRepository f5BiTunnelRepository;
    @Autowired
    private F5BiPartitionRepository f5BiPartitionRepository;
    @Autowired
    private TencentTransportor tencentTransportor;
    @Autowired
    private RegionRepository regionRepository;
    @Autowired
    private FlavorRepository flavorRepository;
    @Autowired
    private FloatingIpRepository floatingIpRepository;
    @Autowired
    private KeypairRepository keypairRepository;
    @Autowired
    private SubnetRepository subnetRepository;
    @Autowired
    private ZoneRepository zoneRepository;
    @Autowired
    private RouterRepository routerRepository;
    @Autowired
    private HuaweiTransportor huaweiTransportor;
    @Autowired
    private KingCloudTransportor kingCloudTransportor;
    @Autowired
    private JdcloudTransportor jdcloudTransportor;
    @Autowired
    private AliyunTransportor aliyunTransportor;
    @Autowired
    private KubernetesTransportor kubernetesTransportor;
    @Autowired
    private QcloudTransportor qcloudTransportor;
    @Autowired
    private PortRepository portRepository;
    @Autowired
    private RouterRepository routeRepository;
    @Autowired
    private FirewallPolicyRepository firewallPolicyRepository;
    @Autowired
    private FirewallRuleRepository firewallRuleRepository;
    @Autowired
    private LoadBalancerRepository loadBalancerRepository;
    @Autowired
    private LbListenerRepository lbListenerRepository;
    @Autowired
    private LbMemberRepository lbMemberRepository;
    @Autowired
    private LbPoolRepository lbPoolRepository;
    @Autowired
    private HealthMonitorRepository healthMonitorRepository;
    @Autowired
    private ObjectStorageContainerRepository objectStorageContainerRepository;
    @Autowired
    private ObjectStorageItemRepository objectStorageItemRepository;
    @Autowired
    private PortFixedIpRepository portFixedIpRepository;
    @Autowired
    private TenantNetworkRepository tenantNetworkRepository;
    @Autowired
    private ObjectRelationRepository objectRelationRepository;
    @Autowired
    private RouterSubnetRepository routerSubnetRepository;
    @Autowired
    private ServerOperationHelper serverOperationHelper;
    @Autowired
    private VolumeTypeRepository volumeTypeRepository;
    @Autowired
    private CosInternalService cosInternalService;
    @Autowired
    private QosPolicyRepository qosPolicyRepository;
    @Autowired
    private QosPolicyRulesRepository qosPolicyRulesRepository;
    @Autowired
    private OSTenantRepository osTenantRepository;
    @Autowired
    private StackTemplateVersionRepository stackTemplateVersionRepository;
    @Autowired
    private CloudStackService cloudStackService;
    @Autowired
    private VpnConnRepository vpnConnRepository;
    @Autowired
    private VpnPolicyRepository vpnPolicyRepository;
    @Autowired
    private CloudStackRepository cloudStackRepository;
    @Autowired
    private AutoScalingRepository autoScalingRepository;
    @Autowired
    private VpnRepository vpnRepository;
    @Autowired
    private FirewallRepository firewallRepository;
    @Autowired
    private AzureTransportor azureTransportor;
    @Autowired
    private AwsTransportor awsTransportor;
    @Autowired
    private PbmProfileDriver profileDriver;
    @Autowired
    private PbmProfileRepository profileRepository;
    @Autowired
    private ManageOneVdcRepository manageOneVdcRepository;
    @Autowired
    private ManageOneProjectRepository projectRepository;
    @Autowired
    private ScsiLunRepository scsiLunRepository;
    @Autowired
    private VpcRepository vpcRepository;
    @Autowired
    private TceTransportor tceTransportor;
    @Autowired
    private ManageOneAccountRepository accountRepository;
    @Autowired
    private IpPoolPortGroupRepository ipPoolPortGroupRepository;
    @Autowired
    private StorageRepository storageRepository;
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private DictionaryRepository dictionaryRepository;
    @Autowired
    private VAppRepository vAppRepository;
    @Autowired
    private VmwareHorizonDesktopPoolRepository desktopPoolRepository;
    @Autowired
    private VmwareHorizonSessionRepository sessionRepository;
    @Autowired
    private VmwareHorizonUserOrGroupRepository userOrGroupRepository;
    @Autowired
    private VmwareHorizonVcenterRepository vcenterRepository;
    @Autowired
    private VmwareHorizonVcenterRelationRepository vcenterRelationRepository;
    @Autowired
    private VmwareHorizonFarmRepository farmRepository;
    @Autowired
    private H3cTransportor h3cTransportor;
    @Autowired
    private SmsDictionaryService smsDictionaryService;
    @Autowired
    private InstanceMessageDispatcher messageDispatcher;
    @Autowired
    private PoolGroupRepository poolGroupRepository;
    @Autowired
    private PoolGroupZoneRepository poolGroupZoneRepository;
    @Autowired
    private ContentLibraryRepository contentLibraryRepository;
    @Autowired
    private ContentLibraryItemRepository itemRepository;
    @Autowired
    private F5BiDataGroupRepository f5BiDataGroupRepository;
    @Autowired
    private SnapshotTaskService snapshotTaskService;
    @Autowired
    private ServerKeypairRepository serverKeypairRepository;
    @Autowired
    private ElasticIpRepository elasticIpRepository;
    @Autowired
    private NatGatewayRepository natGatewayRepository;
    @Autowired
    private NatGatewaySnatRuleRepository natGatewaySnatRuleRepository;
    @Autowired
    private NatGatewayDnatRuleRepository natGatewayDnatRuleRepository;
    @Autowired
    private CidrBlockRepository cidrBlockRepository;
    @Autowired
    private InternetGatewayRepository internetGatewayRepository;
    @Autowired
    private NetworkInterfaceRepository networkInterfaceRepository;

    @Override
    public BocloudResult sync(Long id, RequestContext context, boolean isAuto) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(id);
            if (null == vendor) {
                logger.error("平台数据不存在!");
                return new BocloudResult<>(false, "平台数据不存在");
            }
            // 获取云平台类型
            CloudProvider type = CloudProvider.valueOf(vendor.getType());
            // F5纳管云平台同步操作，主备需要对主device进行检测是否正常运行或是否有对F5进行主备变更的操作。
            if ("F5".equals(vendor.getType())) {
                BocloudResult bocloudResult = activeStandbySwitch(vendor);
                if (bocloudResult.isFailed()) {
                    logger.error("主备同步失败!");
                    return new BocloudResult<>(false, bocloudResult.getMessage());
                }
            }
            // 启动一个线程
            new Thread(() -> {
                Date startTime = new Date();
                String path = CloudVendor.class.getSimpleName() + "_" + vendor.getId();
                String operate = vendor.getType().toLowerCase() + ".sync";
                BocloudResult result = new BocloudResult<>(false, "暂不支持");
                OperateResult operateResult = new OperateResult(true, "同步成功", operate,
                        MapTools.simpleMap("vendorId", vendor.getId()), OperateResult.OperateCategory.ResourceEvent,
                        context);
                try (BocloudACLock lock = lockFactory.getACLock(path)) {
                    Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "当前平台可能存在同步任务或资源处于申请中.");
                    CloudVendor cloudVendor = cloudVendorRepository.query(id);
                    if (null == cloudVendor) {
                        logger.error("平台数据不存在!");
                        result = new BocloudResult<>(false, "平台数据不存在!");
                        operateResult.setSuccess(false);
                        operateResult.setMessage("平台数据不存在！");
                    }
                    if (operateResult.isSuccess()) {
                        logger.info("开始执行云平台{} 的同步操作", vendor.getName());
                        if (CloudProvider.HUAWEI.name().equals(cloudVendor.getType())
                                || CloudProvider.TENCENT.name().equals(cloudVendor.getType())
                                || CloudProvider.ALIYUN.name().equals(cloudVendor.getType())
                                || CloudProvider.TCE.name().equals(cloudVendor.getType())
                                || CloudProvider.QCLOUD.name().equals(cloudVendor.getType())
                                || CloudProvider.TIANYI.name().equals(cloudVendor.getType())
                                || CloudProvider.AWS.name().equals(cloudVendor.getType())
                                || CloudProvider.JDCLOUD.name().equals(cloudVendor.getType())
                                || CloudProvider.AZURE.name().equals(cloudVendor.getType())){
                            result = new BocloudResult<>(true, "ok");
                        } else {
                            result = locationDriver.sync(vendor.getUuid());
                        }
                        if (result.isSuccess()) {
                            switch (type) {
                                case OPENSTACK:
                                    OpenstackTransportor toolOS = new OpenstackTransportor(regionRepository,
                                            cloudServerRepository, serverRepository, networkRepository, subnetRepository,
                                            volumeRepository, snapshotRepository, imageRepository, flavorRepository,
                                            portRepository, routerRepository, serverConfigRepository,
                                            serverAssetsRepository, resourceRepository, ipRepository,
                                            securityGroupRepository, securityGroupRuleRepository, serverSgroupRepository,
                                            firewallRepository, firewallPolicyRepository, firewallRuleRepository,
                                            floatingIpRepository, loadBalancerRepository, lbListenerRepository,
                                            lbMemberRepository, lbPoolRepository, healthMonitorRepository,
                                            objectStorageContainerRepository, objectStorageItemRepository,
                                            portFixedIpRepository, keypairRepository, tenantNetworkRepository,
                                            objectRelationRepository, routerSubnetRepository, cosInternalService,
                                            amqpTemplate, serverOperationHelper, ipPoolRepository, clusterRepository,
                                            serverLabelRepository, ipService, volumeTypeRepository, qosPolicyRepository,
                                            qosPolicyRulesRepository, osTenantRepository, clusterNodeRepository,
                                            cloudStackRepository, stackTemplateVersionRepository, vpnRepository,
                                            vpnPolicyRepository, vpnConnRepository, cloudStackService,
                                            autoScalingRepository, vpcRepository, messageDispatcher);
                                    result = toolOS.sync(vendor, result.getData(), context.getTarget());
                                    break;
                                case H3C:
                                    result = h3cTransportor.sync(vendor, result.getData(), context.getTarget());
                                    break;
                                case VMWARE:
                                    VmwareTransportor tool = new VmwareTransportor(vdcRepository, cloudServerRepository,
                                            dataStoreRepository, snapshotRepository, networkRepository, clusterRepository,
                                            storeHostRepository, serverRepository, networkCardRepository,
                                            portGroupRepository, networkHostRepository, clusterNodeRepository,
                                            serverConfigRepository, serverAssetsRepository, resourceRepository,
                                            ipRepository, ipPoolRepository, imageRepository, switcherRepository,
                                            resourcePoolRepository, volumeRepository, serverLabelRepository,
                                            amqpTemplate, ipService, locationDriver, profileDriver,
                                            profileRepository, scsiLunRepository, ipPoolPortGroupRepository, vAppRepository,
                                            taskExecutor, messageDispatcher, snapshotTaskService);
                                    result = tool.sync(vendor, result.getData(), context.getTarget());
                                    new Thread(() -> {
                                        // 同步内容库
                                        this.syncContentLibraries(vendor.getId(), context);
                                    }).start();
                                    this.syncAlarm(vendor, context.getTarget());
                                    break;
                                case HMC:
                                    result = hmcTransportor.sync(vendor, result.getData(), context.getTarget());
                                    // result = hmdTransportor.sync(vendor, result.getData(), context.getTarget());
                                    break;
                                case TENCENT:
                                    result = syncPublicCloud(context, vendor, tencentTransportor);
                                    break;
                                case HUAWEI:
                                    result = syncPublicCloud(context, vendor, huaweiTransportor);
                                    break;
                                case KINGCLOUD:
                                    result = syncPublicCloud(context, vendor, kingCloudTransportor);
                                    break;
                                case JDCLOUD:
                                    result = syncPublicCloud(context, vendor, jdcloudTransportor);
                                    break;
                                case ALIYUN:
                                    result = syncPublicCloud(context, vendor, aliyunTransportor);
                                    break;
                                case QCLOUD:
                                    result = syncPublicCloud(context, vendor, qcloudTransportor);
                                    break;
                                case KUBERNETES:
                                    result = kubernetesTransportor.sync(vendor, result.getData(), context.getTarget());
                                    break;
                                case F5:
                                    F5Transportor f5Transportor = new F5Transportor(f5BiNodeRepository,
                                            f5BiProfileRepository, f5BiMonitorRepository, f5BiPoolRepository,
                                            f5BiPoolMemberRepository, f5BiVirtualServerRepository, f5BiIRulesRepository,
                                            f5BiDnsResolversRepository, f5BiSnatPoolRepository, f5BiVlanRepository,
                                            f5BiTunnelRepository, f5BiPartitionRepository, f5BiDataGroupRepository);
                                    result = f5Transportor.sync(vendor, result.getData(), context.getTarget());
                                    break;
                                case FUSIONCLOUD:
                                    FusionCloudTransportor fusionCloudTransportor = new FusionCloudTransportor(
                                            networkRepository, snapshotRepository, imageRepository, flavorRepository,
                                            cloudServerRepository, subnetRepository, regionRepository, volumeRepository,
                                            portRepository, routeRepository, resourceRepository, ipRepository,
                                            securityGroupRepository, securityGroupRuleRepository, serverSgroupRepository,
                                            portFixedIpRepository, keypairRepository, tenantNetworkRepository,
                                            routerSubnetRepository, serverOperationHelper, ipPoolRepository,
                                            serverLabelRepository, ipService, serverRepository, serverConfigRepository,
                                            floatingIpRepository, volumeTypeRepository);
                                    result = fusionCloudTransportor.sync(vendor, result.getData(), context.getTarget());
                                    break;
                                case MANAGEONE:
                                    // 查询所有vdc下数据
                                    String content = JSONObject.toJSONString(result.getData());
                                    ManageOneSyncModel model = JSONObject.parseObject(content, ManageOneSyncModel.class);
                                    List<ManageOneAccount> accounts = accountRepository.listByVendorId(vendor.getId());
                                    for (ManageOneAccount account : accounts) {
                                        logger.info("开始查询VDC下用户{}的资源数据", account.getUsername());
                                        BocloudResult bocloudResult = locationDriver.sync(vendor.getUuid(),
                                                account.getUsername(), account.getPassword(), account.getProjectId(),
                                                account.getDomainName());
                                        if (bocloudResult.isSuccess()) {
                                            String vdcContent = JSONObject.toJSONString(bocloudResult.getData());
                                            ManageOneSyncModel vdcModel = JSONObject.parseObject(vdcContent,
                                                    ManageOneSyncModel.class);
                                            model.setServerModels(ManageOneSyncModel.addAll(model.getServerModels(),
                                                    vdcModel.getServerModels()));
                                            model.setNetworkModels(ManageOneSyncModel.addAll(model.getNetworkModels(),
                                                    vdcModel.getNetworkModels()));
                                            model.setVolumeModels(ManageOneSyncModel.addAll(model.getVolumeModels(),
                                                    vdcModel.getVolumeModels()));
                                            model.setSnapshotModels(ManageOneSyncModel.addAll(model.getSnapshotModels(),
                                                    vdcModel.getSnapshotModels()));
                                            model.setImageModels(ManageOneSyncModel.addAll(model.getImageModels(),
                                                    vdcModel.getImageModels()));
                                            model.setFlavorModels(ManageOneSyncModel.addAll(model.getFlavorModels(),
                                                    vdcModel.getFlavorModels()));
                                            model.setPortModels(ManageOneSyncModel.addAll(model.getPortModels(),
                                                    vdcModel.getPortModels()));
                                            model.setRouterModels(ManageOneSyncModel.addAll(model.getRouterModels(),
                                                    vdcModel.getRouterModels()));
                                            model.setGroupModels(ManageOneSyncModel.addAll(model.getGroupModels(),
                                                    vdcModel.getGroupModels()));
                                            model.setKeypairModels(ManageOneSyncModel.addAll(model.getKeypairModels(),
                                                    vdcModel.getKeypairModels()));
                                            model.setFloatingIpModels(ManageOneSyncModel.addAll(model.getFloatingIpModels(),
                                                    vdcModel.getFloatingIpModels()));
                                            model.setFirewallModels(ManageOneSyncModel.addAll(model.getFirewallModels(),
                                                    vdcModel.getFirewallModels()));
                                            model.setFirewallPolicyModels(ManageOneSyncModel.addAll(
                                                    model.getFirewallPolicyModels(), vdcModel.getFirewallPolicyModels()));
                                            model.setFirewallRuleModels(ManageOneSyncModel.addAll(
                                                    model.getFirewallRuleModels(), vdcModel.getFirewallRuleModels()));
                                            model.setVpcModels(ManageOneSyncModel.addAll(model.getVpcModels(),
                                                    vdcModel.getVpcModels()));
                                        }
                                    }
                                    model = ManageOneSyncModel.distinct(model);
                                    ManageOneTransportor manageOneTransportor = new ManageOneTransportor(networkRepository,
                                            snapshotRepository, imageRepository, flavorRepository, cloudServerRepository,
                                            subnetRepository, regionRepository, volumeRepository, portRepository,
                                            routeRepository, resourceRepository, ipRepository, securityGroupRepository,
                                            securityGroupRuleRepository, serverSgroupRepository, portFixedIpRepository,
                                            keypairRepository, tenantNetworkRepository, routerSubnetRepository,
                                            serverOperationHelper, ipPoolRepository, serverLabelRepository, ipService,
                                            serverRepository, serverConfigRepository, floatingIpRepository,
                                            volumeTypeRepository, firewallRepository, firewallPolicyRepository,
                                            firewallRuleRepository, manageOneVdcRepository, projectRepository,
                                            vpcRepository, storageRepository);
                                    result = manageOneTransportor.sync(vendor, model, context.getTarget());
                                    break;
                                case POWERVC:
                                    result = powervcTransportor.sync(vendor, result.getData(), context.getTarget());
                                    break;
                                case AZURE:
                                    result = syncPublicCloud(context, vendor, azureTransportor);
                                    break;
                                case AWS:
                                    result = syncPublicCloud(context, vendor, awsTransportor);
                                    break;
                                case TCE:
                                    result = syncPublicCloud(context, vendor, tceTransportor);
                                    break;
                                case TIANYI:
                                    result = syncPublicCloud(context, vendor, tianyiTransportor);
                                    break;
                                case HORIZON:
                                    VmwareHorizonTransportor horizonTransportor = new VmwareHorizonTransportor(
                                            desktopPoolRepository, sessionRepository, userOrGroupRepository,
                                            vcenterRepository, vcenterRelationRepository, farmRepository,
                                            cloudVendorRepository);
                                    result = horizonTransportor.sync(vendor, result.getData(), context.getTarget());
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                    logger.info("云平台同步任务结果：{}", result.getMessage());
                    operateResult.setSuccess(result.isSuccess());
                    operateResult.setMessage(result.getMessage());
                } catch (Exception e) {
                    logger.error("当前云平台存在同步任务异常", e);
                    operateResult.setSuccess(false);
                    operateResult.setMessage("云平台同步失败：" + e.getMessage());
                }
                if (!isAuto) {
                    resourceEventPublisher.send(operateResult);
                }
                VendorSyncRecord record = new VendorSyncRecord();
                record.setVendorId(vendor.getId());
                record.setStartTime(startTime);
                record.setEndTime(new Date());
                record.setCost(record.getEndTime().getTime() - startTime.getTime());
                record.setResult(operateResult.getMessage());
                record.setCreatorId(context.getTarget());
                record.setSyncResult(operateResult.isSuccess());
                record.setAuto(isAuto);
                amqpTemplate.convertAndSend("vendor.record.queue", record);
                if (operateResult.isSuccess()) {
                    // 发送给云平台统计队列对云平台重新统计
                    JSONObject object = new JSONObject();
                    object.put(Common.VENDORID, vendor.getId());
                    amqpTemplate.convertAndSend("vendor.statistics.queue", object);
                }
                // 更新云平台最后一次同步时间
                vendor.setGmtModify(record.getEndTime());
                vendor.setMenderId(context.getTarget());
                cloudVendorRepository.update(vendor);
            }).start();
            return new BocloudResult<>(true, "同步任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("sync cloudvendor exception ", e);
            return new BocloudResult<>(false, "同步失败!");
        }
    }

    /**
     * 主备切换操作
     */
    private BocloudResult activeStandbySwitch(CloudVendor vendor) {
        try {
            Boolean isVerify = false;
            JSONObject authentication = JSONObject.parseObject(vendor.getAuthentication());
            BocloudResult bocloudResult = f5DeviceDriver.list(vendor.getUuid());
            if (bocloudResult.isFailed()) {
                logger.warn("F5主设备异常，尝试切换备用设备。。。");
                String[] managementIps = StringUtils.substringBefore(
                        StringUtils.substringAfter(authentication.getString("managementIps"), "["), "]").split(",");
                if (0 == managementIps.length) {
                    return new BocloudResult<>(false, "设备异常请检查！");
                }
                for (String managementIp : managementIps) {
                    if ("".equals(managementIp) || null == managementIp) {
                        continue;
                    }
                    // 更新Butler
                    List<CloudVendor> cloudVendors = cloudVendorRepository.listAll();
                    for (CloudVendor cloudVendor : cloudVendors) {
                        if (cloudVendor.getId().equals(vendor.getId())) {
                            authentication.put("address", "https://" + managementIp + ":443");
                            cloudVendor.setAuthentication(JSONObject.toJSONString(authentication));
                            cloudVendorRepository.update(cloudVendor);
                            break;
                        }
                    }
                    this.providerRegister.updateProvider(cloudVendors);
                    BocloudResult resultData = f5DeviceDriver.list(vendor.getUuid());
                    if (resultData.isSuccess()) {
                        List<JSONObject> devices = JSONObject.parseObject(resultData.getMessage()).getJSONArray("items")
                                .toJavaList(JSONObject.class);
                        for (JSONObject device : devices) {
                            if (managementIp.equals(device.getString("managementIp"))
                                    && "active".equals(device.getString("failoverState"))) {
                                isVerify = true;
                                break;
                            }
                        }
                    } else {
                        continue;
                    }
                    if (isVerify) {
                        break;
                    }
                }
                if (!isVerify) {
                    // 若主备切换失败则需要zk上数据回滚
                    List<CloudVendor> cloudVendors = cloudVendorRepository.listAll();
                    for (CloudVendor cloudVendor : cloudVendors) {
                        if (cloudVendor.getId().equals(vendor.getId())) {
                            JSONObject oldAuth = JSONObject.parseObject(cloudVendor.getAuthentication());
                            oldAuth.put("address", authentication.getString("address"));
                            cloudVendor.setAuthentication(JSONObject.toJSONString(oldAuth));
                            cloudVendorRepository.update(cloudVendor);
                            break;
                        }
                    }
                    return new BocloudResult<>(false, "纳管F5 device服务主备异常请检查重试!");
                }
            } else {
                List<JSONObject> f5Devices = JSONObject.parseObject(bocloudResult.getMessage()).getJSONArray("items")
                        .toJavaList(JSONObject.class);
                JSONObject f5Device = new JSONObject();
                String masterAddress = null;
                for (JSONObject device : f5Devices) {
                    String f5Address = "https://" + device.getString("managementIp") + ":443";
                    if (f5Address.equals(authentication.getString("address"))) {
                        f5Device = device;
                    }
                    if ("active".equals(device.getString("failoverState"))) {
                        masterAddress = device.getString("managementIp");
                    }
                }
                // 若当前device不为主device 则需要进行主备切换操作
                if (!"active".equals(f5Device.getString("failoverState"))) {
                    // 更新Butler
                    List<CloudVendor> cloudVendors = cloudVendorRepository.listAll();
                    for (CloudVendor cloudVendor : cloudVendors) {
                        if (cloudVendor.getId().equals(vendor.getId())) {
                            authentication.put("address", "https://" + masterAddress + ":443");
                            vendor.setAuthentication(JSONObject.toJSONString(authentication));
                        }
                    }
                    this.providerRegister.updateProvider(cloudVendors);
                }
            }
            // 更新主备ip群
            BocloudResult result = f5DeviceDriver.list(vendor.getUuid());
            if (result.isFailed()) {
                logger.error(result.getMessage());
                return new BocloudResult<>(false, "获取主备设备失败");
            }
            List<JSONObject> f5Devices = JSONObject.parseObject(result.getMessage()).getJSONArray("items")
                    .toJavaList(JSONObject.class);
            List<Object> managementIps = com.google.common.collect.Lists.newArrayList();
            for (JSONObject device : f5Devices) {
                if (!"active".equals(device.getString("failoverState"))) {
                    managementIps.add(device.getString("managementIp"));
                }
            }
            CloudVendor cloudVendor = cloudVendorRepository.query(vendor.getId());
            // 主备切换成功更新虚拟机状态（需判断下是否主备都已挂掉，若主备都挂掉，则需要将备用设备ip池中的主设备ip删除）
            Iterator<Object> iterator = managementIps.iterator();
            while (iterator.hasNext()) {
                Object managementIp = iterator.next();
                if (managementIp.equals(authentication.getString("address"))) {
                    iterator.remove();
                }
            }
            JSONObject oldAuth = JSONObject.parseObject(cloudVendor.getAuthentication());
            oldAuth.put("managementIps", String.valueOf(managementIps));
            cloudVendor.setAuthentication(JSONObject.toJSONString(oldAuth));
            cloudVendor.setStatus(BaseStatus.NORMAL.name());
            cloudVendorRepository.update(cloudVendor);
        } catch (Exception e) {
            logger.error("Active-Standby Switch IS ERROR:", e);
            return new BocloudResult<>(false, e.getMessage());
        }
        return new BocloudResult<>(true, "主备切换完成!");
    }

    @Override
    public void syncAlarm(CloudVendor vendor, Long userId) {
        // 认证是否合法
        if (authDriver.auth(vendor.getUuid(), null).isFailed()) {
            logger.error("同步告警时 云平台  {} 认证失败！", vendor.getName());
            return;
        }
        new AlarmSyncTask(userId, vendor, alarmRepository, alarmDriver, amqpTemplate).execute();
    }

    /**
     * 同步平台指定类型数据
     *
     * @param id
     * @param context
     * @param syncType
     * @return
     */
    @Override
    public BocloudResult sync(Long id, RequestContext context, SyncType syncType) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(id);
            if (null == vendor) {
                logger.error("平台数据不存在!");
                return new BocloudResult<>(false, "平台数据不存在");
            }
            // 获取云平台类型
            CloudProvider type = CloudProvider.valueOf(vendor.getType());
            // 启动一个线程
            new Thread(() -> {
                Date startTime = new Date();
                String path = CloudVendor.class.getSimpleName() + "_" + vendor.getId() + "_" + syncType.name();
                String operate = vendor.getType().toLowerCase() + ".sync";
                BocloudResult result = new BocloudResult<>(false, "暂不支持");
                OperateResult operateResult = new OperateResult(true, "同步成功", operate,
                        MapTools.simpleMap("vendorId", vendor.getId()), OperateResult.OperateCategory.ResourceEvent,
                        context);
                try (BocloudACLock lock = lockFactory.getACLock(path)) {
                    Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
                    CloudVendor cloudVendor = cloudVendorRepository.query(id);
                    if (null == cloudVendor) {
                        logger.error("平台数据不存在!");
                        result = new BocloudResult<>(false, "平台数据不存在!");
                        operateResult.setSuccess(false);
                        operateResult.setMessage("平台数据不存在！");
                    }
                    if (operateResult.isSuccess()) {
                        logger.info("开始执行云平台{} 的同步操作", vendor.getName());
                        if (CloudProvider.HUAWEI.name().equals(cloudVendor.getType())
                                || CloudProvider.ALIYUN.name().equals(cloudVendor.getType())
                                || CloudProvider.AWS.name().equals(cloudVendor.getType())
                                || CloudProvider.AZURE.name().equals(cloudVendor.getType())) {
                            result = new BocloudResult<>(true, "ok");
                        }
                        if (result.isSuccess()) {
                            switch (type) {
                                case AWS:
                                    switch (syncType) {
                                        case LOAD_BALANCER:
                                            result = awsTransportor.syncAwsLB(vendor, context);
                                            break;
                                        default:
                                            break;
                                    }
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                    logger.info("云平台同步任务结果：{}", result.getMessage());
                    operateResult.setSuccess(result.isSuccess());
                    operateResult.setMessage(result.getMessage());
                } catch (Exception e) {
                    logger.error("当前云平台存在同步任务异常", e);
                    operateResult.setSuccess(false);
                    operateResult.setMessage("当前云平台存在同步任务异常");
                }
                resourceEventPublisher.send(operateResult);
                VendorSyncRecord record = new VendorSyncRecord();
                record.setVendorId(vendor.getId());
                record.setStartTime(startTime);
                record.setEndTime(new Date());
                record.setCost(record.getEndTime().getTime() - startTime.getTime());
                record.setResult(operateResult.getMessage());
                record.setCreatorId(context.getTarget());
                record.setSyncResult(operateResult.isSuccess());
                amqpTemplate.convertAndSend("vendor.record.queue", record);
                if (operateResult.isSuccess()) {
                    // 发送给云平台统计队列对云平台重新统计
                    JSONObject object = new JSONObject();
                    object.put(Common.VENDORID, vendor.getId());
                    amqpTemplate.convertAndSend("vendor.statistics.queue", object);
                }
                // 更新云平台最后一次同步时间
                vendor.setGmtModify(record.getEndTime());
                vendor.setMenderId(context.getTarget());
                cloudVendorRepository.update(vendor);
            }).start();
            return new BocloudResult<>(true, "同步任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("sync cloudvendor exception ", e);
            return new BocloudResult<>(false, "同步失败!");
        }
    }

    /**
     * 单独同步云平台网络，交换机，端口组数据
     */
    @SuppressWarnings("unchecked")
    @Override
    public BocloudResult syncVcenterNetwork(CloudVendor vendor, Long userId) {
        try {
            ButlerRepository butlerRepository = ButlerRepository.getInstance();
            if (null == butlerRepository.get(vendor.getUuid())) {
                return new BocloudResult<>(false, "网络同步失败，云平台认证信息不存在");
            }
            VmwareProvider provider = new VmwareProvider(butlerRepository.get(vendor.getUuid()));
            ManagedEntity[] dcEntities = new InventoryNavigator(provider.getRootFolder())
                    .searchManagedEntities(VmwareProvider.DC);
            if (null != dcEntities) {
                for (ManagedEntity entity : dcEntities) {
                    Datacenter datacenter = (Datacenter) entity;
                    List<NetworkModel> networkList = new ArrayList<>();
                    List<SwitchModel> switcherList = new ArrayList<>();
                    // 组装网络数据
                    Map<String, Object> networkMap = AssembleTools.getInstance().assembleNetwork(datacenter);
                    if (null != networkMap) {
                        networkList = (List<NetworkModel>) networkMap.get("network");
                        switcherList = (List<SwitchModel>) networkMap.get("switcher");
                    }
                    VmwareTransportor transportor = new VmwareTransportor(vdcRepository, cloudServerRepository,
                            dataStoreRepository, snapshotRepository, networkRepository, clusterRepository,
                            storeHostRepository, serverRepository, networkCardRepository, portGroupRepository,
                            networkHostRepository, clusterNodeRepository, serverConfigRepository,
                            serverAssetsRepository, resourceRepository, ipRepository, ipPoolRepository, imageRepository,
                            switcherRepository, resourcePoolRepository, volumeRepository, serverLabelRepository,
                            amqpTemplate, ipService, locationDriver, profileDriver,
                            profileRepository, scsiLunRepository, ipPoolPortGroupRepository, vAppRepository,
                            taskExecutor, messageDispatcher, snapshotTaskService);
                    Vdc vdc = vdcRepository.getByValue(datacenter.getMOR().getVal(), vendor.getId());
                    if (null != vdc) {
                        Long vdcId = vdc.getId();
                        // 同步分布式交换机
                        List<Switcher> switchers = switcherRepository.listByVdc(vdcId, "DVSWITCH");
                        logger.info("Start sync dvswitcher of datacenter[" + vdcId + "]");
                        transportor.syncSwitcher(switchers,
                                JSONArray.parseArray(JSONArray.toJSONString(switcherList), Switcher.class),
                                vendor.getId(), vdcId, null, userId, "DVSWITCH", new ArrayList<>(), vendor.getGuid());
                        // 获取分布式交换机
                        Map<String, Long> dvswitchMap = Maps.newHashMap();
                        Map<String, String> groupMap = Maps.newHashMap();
                        switchers = switcherRepository.listByVdc(vdcId, "DVSWITCH");
                        for (Switcher switcher : switchers) {
                            dvswitchMap.put(switcher.getSwitcherVal(), switcher.getId());
                            List<PortGroup> groups = portGroupRepository.listBySwitcher(switcher.getId());
                            for (PortGroup group : groups) {
                                groupMap.put(group.getGroupVal(), switcher.getSwitcherVal());
                            }
                        }
                        // 同步网络
                        List<Network> oldNetworks = networkRepository.listByVdc(vdc.getId());
                        Map<String, Network> newNetworkMap = new HashMap<>(8);
                        logger.info("Start sync network of datacenter[" + vdcId + "]");
                        transportor.syncNetwork(oldNetworks,
                                JSONArray.parseArray(JSONArray.toJSONString(networkList), Network.class),
                                vendor.getId(), vdc.getId(), userId, newNetworkMap, dvswitchMap, null, vendor.getGuid(),
                                vdc.getGuid());
                    }
                }
            }
            return new BocloudResult<>(true, "网络同步成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "网络同步失败");
        }
    }

    private BocloudResult syncPublicCloud(RequestContext context, CloudVendor vendor, Transportor transportor) {
        BocloudResult result = new BocloudResult<>(true, "云平台同步成功！");
        Long userId = context.getTarget();
        try {
            // 平台配置信息
            JSONObject authentication = JSONObject.parseObject(vendor.getAuthentication());
            String regions = authentication.getString("regions");
            List<String> currentRegions = JSONObject.parseArray(regions, String.class);
            if (ListTool.isEmpty(currentRegions)) {
                throw new RuntimeException("区域信息异常！");
            }

            // cmdb
            CmdbModel model = new CmdbModel();
            model.setUuid(IDFactory.instance().uuid());
            model.setServiceName(BoCloudService.IMS.name());
            model.setManagerId(userId);
            List<CmdbInfo> infos = new ArrayList<>();

            // 汉化区域
            this.syncRegion(vendor, userId, currentRegions);

            // CMDB数据需要
            List<String> regionsName = new ArrayList<>();
            List<String> codes = JSON.parseArray(regions, String.class);
            List<Region> vendorRegions = regionRepository.listByRegions(vendor.getId(), codes);
            for (Region region : vendorRegions) {
                regionsName.add(region.getName());
            }
            vendor.setRegionsName(String.valueOf(regionsName));

            infos.add(CmdbInfoConvertor.getInfo(vendor, null, null));
            // cmdb 顺序放置资源

            List<Region> newRegionList = regionRepository.list(vendor.getId());
            for (Region newReg : newRegionList) {
                List<CmdbRelation> relations = new ArrayList<>();
                relations.add(new CmdbRelation(ModuleCode.VENDOR.name(), 1L, ListUtils.getList(vendor.getGuid())));
                newReg.setName(newReg.getName() + " | " + vendor.getName() + "平台");
                infos.add(CmdbInfoConvertor.getInfo(newReg, null, relations));
                result = locationDriver.sync(vendor.getUuid(), newReg.getCode());
                if (result.isFailed()) {
                    break;
                }
                result = transportor.sync(vendor, result.getData(), newReg, userId, infos);
                if (result.isFailed()) {
                    break;
                }
            }
            // 资源同步成功后 创建资源池 同步CMDB
            if (result.isSuccess()) {
                // 创建资源池
                this.createPoolGroup(vendor, context);
                model.setData(infos);
                // 发送消息到cmdb模块，进行数据同步
                CloudProvider type = CloudProvider.valueOf(vendor.getType());
                switch (type) {
                    case TENCENT:
                        messageDispatcher.cacheMessage(JSONObject.toJSONString(model));
                        break;
                    default:
                        break;
                }
            }

        } catch (Exception e) {
            logger.error("sync failure:", e);
            result = new BocloudResult<>(false, e.getMessage());
        }
        return result;
    }

    private void createPoolGroup(CloudVendor vendor, RequestContext context) {
        try {
            CloudProvider cloudProvider = CloudProvider.valueOf(vendor.getType());
            switch (cloudProvider) {
                case ALIYUN:
                case HUAWEI:
                case TENCENT:
                case QCLOUD:
                case TIANYI:
                case AWS:
                    List<Region> regions = regionRepository.listByVendorId(vendor.getId());
                    if (ListTool.isEmpty(regions)) {
                        return;
                    }
                    for (Region region : regions) {
                        PoolGroup poolGroup = poolGroupRepository.getByRegion(region.getRegionId(), vendor.getId());
                        if (null == poolGroup) {
                            String name = vendor.getName() + "_" + region.getName() + "_资源池";
                            // 创建公有云资源池
                            poolGroup = new PoolGroup();
                            poolGroup.setName(name);
                            poolGroup.setRemark(name);
                            poolGroup.setVendorType(vendor.getType());
                            poolGroup.setRegion(region.getRegionId());
                            poolGroup.setVendorId(vendor.getId());
                            poolGroup.setBindingPolicy("share");
                            poolGroup.setCategory("COMPUTER");
                            poolGroup.setStatus("NORMAL");// 启用
                            poolGroup.setParentId(0L);
                            poolGroup.setCreatorId(context.getTarget());
                            poolGroup.setMenderId(context.getTarget());
                            poolGroup.setIsPublic(true);
                            poolGroupRepository.save(poolGroup);
                            this.savePoolGroupZoneRelation(region, vendor, poolGroup);
                        }
                    }
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            logger.error("资源池创建失败：" + e.getMessage());
        }
    }

    private void savePoolGroupZoneRelation(Region region, CloudVendor vendor, PoolGroup poolGroup) {
        try {
            List<PoolGroupZone> poolGroupZones = poolGroupZoneRepository.listByGroupId(vendor.getId(),
                    poolGroup.getId(), region.getRegionId(), null);
            if (!ListTool.isEmpty(poolGroupZones)) {
                poolGroupZoneRepository.remove(poolGroup.getId());
            }
            List<Zone> zones = zoneRepository.listByRegionId(region.getRegionId(), vendor.getId());
            if (!ListTool.isEmpty(zones)) {
                PoolGroupZone poolGroupZone = null;
                for (Zone zone : zones) {
                    poolGroupZone = new PoolGroupZone();
                    poolGroupZone.setVendorId(vendor.getId());
                    poolGroupZone.setPoolGroupId(poolGroup.getId());
                    poolGroupZone.setRegionId(region.getRegionId());
                    poolGroupZone.setZoneId(zone.getZoneId());
                    poolGroupZone.setChecked(true);
                    poolGroupZoneRepository.save(poolGroupZone);
                }
            }
        } catch (Exception e) {
            logger.error("保存资源池可用区异常：" + e.getMessage());
        }
    }

    public Map<String, String> dicToMap(String vendorType) throws Exception {
        Map<String, String> dicMap = new HashMap<String, String>(8);
        BocloudResult<List<Dictionary>> dictionarieResult = smsDictionaryService.dictionaries(vendorType + "_REGION");
        if (dictionarieResult.isFailed()) {
            throw new RuntimeException("查询区域字段异常：" + dictionarieResult.getMessage());
        }
        List<Dictionary> dictionaries = dictionarieResult.getData();
        if (!ListTool.isEmpty(dictionaries)) {
            for (Dictionary dictionary : dictionaries) {
                dicMap.put(dictionary.getValue(), dictionary.getName());
            }
        }
        return dicMap;
    }

    /**
     * 同步纳管时选择的区域
     *
     * @param vendor
     * @throws Exception
     */
    private void syncRegion(CloudVendor vendor, Long userId, List<String> currentRegions) throws Exception {
        // 平台当前区域信息
        List<Region> oldRegionList = regionRepository.list(vendor.getId());
        Map<String, Region> oldRegionMap = new HashMap<>(8);
        for (Region oldR : oldRegionList) {
            oldRegionMap.put(oldR.getCode(), oldR);
        }
        // 同步 区域信息
        BocloudResult listRegions = locationDriver.listRegions(vendor.getUuid(), currentRegions.get(0));
        if (listRegions.isFailed()) {
            throw new Exception(listRegions.getMessage());
        }
        List<RegionModel> regList = JSON.parseArray(JSON.toJSONString(listRegions.getData()), RegionModel.class);
        // 获取字典中区域
        Map<String, String> dicToMap = dicToMap(vendor.getType().toUpperCase());
        // 将不需要的区域过滤掉
        for (int i = regList.size() - 1; i >= 0; i--) {
            RegionModel regionModel = regList.get(i);
            String code = regionModel.getCode();
            if (null != dicToMap && dicToMap.containsKey(code)) {
                regionModel.setName(dicToMap.get(code));
            }
            if (!currentRegions.contains(code)) {
                regList.remove(regionModel);
            }
        }
        Region reg = null;
        if (!ListTool.isEmpty(regList)) {
            // 同步区域
            for (RegionModel regionModel : regList) {
                if (oldRegionMap.containsKey(regionModel.getCode())) {
                    reg = oldRegionMap.get(regionModel.getCode());
                    regionModel.setGuid(reg.getGuid());
                    BeanUtils.copyProperties(regionModel, reg);
                    reg.setVendorId(vendor.getId());
                    regionRepository.update(reg);
                    oldRegionMap.remove(regionModel.getCode());
                    continue;
                }
                reg = new Region();
                BeanUtils.copyProperties(regionModel, reg);
                reg.setVendorId(vendor.getId());
                reg.setGuid(UUID.randomUUID().toString().replaceAll("-", ""));
                regionRepository.save(reg);
            }
            // 删除区域
            for (Entry<String, Region> entry : oldRegionMap.entrySet()) {
                Region region = entry.getValue();
                regionRepository.delete(region.getId());
                // 删除区域下对应的资源
                removeResources(region.getRegionId(), vendor.getId(), userId);
            }
        }
    }

    public void removeResources(String regionId, Long vendorId, Long userId) throws Exception {
    	List<CloudServer> cloudServers = cloudServerRepository.listByVendorId(vendorId, regionId);
        if (!ListTool.isEmpty(cloudServers)) {
            for (CloudServer cloudServer : cloudServers) {
                serverKeypairRepository.removeBySid(cloudServer.getId());
                serverSgroupRepository.removeBySid(cloudServer.getId());
                cloudServerRepository.remove(cloudServer.getId(), userId);
            }
        }
        // 删除原有域下的数据 虚拟安全组关系表 虚拟秘钥关系表
        zoneRepository.deleteByRegionId(regionId, vendorId);
        volumeRepository.removeByVid(vendorId, regionId, userId);
        routerRepository.removeByVid(vendorId, regionId, userId);
        networkRepository.removeByVid(vendorId, regionId, userId);
        imageRepository.removeByVid(vendorId, regionId, userId);
        flavorRepository.removeByVid(vendorId, regionId);
        networkCardRepository.removeByVid(vendorId, regionId, userId);
        floatingIpRepository.removeByVid(vendorId, regionId, userId);
        List<SecurityGroup> listSecurityGroups = securityGroupRepository.listByVendorId(vendorId, regionId);
        for (SecurityGroup group : listSecurityGroups) {
        	securityGroupRuleRepository.removeBySgId(group.getId(), userId);
        }
        securityGroupRepository.removeByVid(vendorId, regionId, userId);
        keypairRepository.removeByVid(vendorId, regionId, userId);
        snapshotRepository.removeByVid(vendorId, regionId, userId);
        subnetRepository.removeByVid(vendorId, regionId, userId);
        resourceRepository.removeByVid(vendorId, regionId, userId);
        vpcRepository.deleteByVid(vendorId, regionId, userId);
        poolGroupRepository.removeByVid(vendorId, regionId, userId);
        elasticIpRepository.removeByVid(vendorId, userId, regionId);
        routeRepository.removeByVid(vendorId, regionId, userId);
        loadBalancerRepository.removeByVid(vendorId, regionId, userId);
        lbListenerRepository.removeByVid(vendorId, userId, regionId);
        lbPoolRepository.removeByVid(vendorId, userId, regionId);
        lbMemberRepository.removeByVid(vendorId, userId, regionId);
        poolGroupZoneRepository.deleteByVid(vendorId, regionId);
        natGatewayRepository.removeByVid(vendorId, regionId, userId);
        natGatewaySnatRuleRepository.removeByVid(vendorId, regionId, userId);
        natGatewayDnatRuleRepository.removeByVid(vendorId, regionId, userId);
        cidrBlockRepository.removeByVid(vendorId, regionId, userId, null);
        internetGatewayRepository.removeByVid(vendorId, userId, regionId);
        networkInterfaceRepository.removeByVid(vendorId, userId, regionId);
    }

    /**
     * 同步安全组
     *
     * @param id
     * @param userId
     * @return
     */
    @Override
    public BocloudResult syncSecurityGroups(Long id, Long userId) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(id);
            if (null == vendor) {
                return new BocloudResult<>(false, "云平台不存在");
            }
            BocloudResult result = locationDriver.syncSecurityGroups(vendor.getUuid());
            if (result.isFailed()) {
                return new BocloudResult<>(false, "安全组同步失败");
            }
            OpenstackTransportor toolOS = new OpenstackTransportor(securityGroupRepository, securityGroupRuleRepository,
                    serverSgroupRepository);
            toolOS.syncSecurityGroup(
                    JSONArray.parseArray(JSONArray.toJSONString(result.getData()), SecurityGroupModel.class),
                    vendor.getId(), userId);
            return new BocloudResult<>(true, "同步成功");
        } catch (Exception e) {
            logger.error("Get error message：{}", e);
            return new BocloudResult<>(false, "同步失败");
        }
    }

    @Override
    public BocloudResult syncContentLibraries(Long vendorId, RequestContext context) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Assert.notNull(vendor, "云平台不存在");
            BocloudResult<List<LibraryModel>> result = locationDriver.listLibraries(vendor.getUuid());
            if (result.isSuccess() && null != result.getData()) {
                logger.info("Start sync content library and items");
                syncLibraries(result.getData(), vendorId, context.getTarget());
                logger.info("End sync content library and items");
            }
            return new BocloudResult(true, "内容库同步成功");
        } catch (Exception e) {
            logger.error("Get error message:{}", e);
            return new BocloudResult(false, "内容库同步失败:" + e.getMessage());
        }
    }

    public void syncLibraries(List<LibraryModel> models, Long vendorId, Long managerId) {
        if (ListTool.isEmpty(models)) {
            List<ContentLibrary> libraries = contentLibraryRepository.listByVendorId(vendorId);
            for (ContentLibrary library : libraries) {
                itemRepository.removeByLibraryId(library.getId(), managerId);
            }
            contentLibraryRepository.removeByVendorId(vendorId, managerId);
            return;
        }
        List<ContentLibrary> libraries = contentLibraryRepository.listByVendorId(vendorId);
        Map<String, ContentLibrary> map = libraries.stream()
                .collect(Collectors.toMap(ContentLibrary::getLibraryUuid, Function.identity(), (v1, v2) -> v2));
        for (LibraryModel model : models) {
            ContentLibrary library = new ContentLibrary();
            if (map.containsKey(model.getLibraryUuid())) {
                library = map.get(model.getLibraryUuid());
                BeanUtils.copyProperties(model, library);
                library.setMenderId(managerId);
                contentLibraryRepository.update(library);
            } else {
                BeanUtils.copyProperties(model, library);
                library.setCreatorId(managerId);
                library.setGmtCreate(new Date());
                library.setVendorId(vendorId);
                library.setTenantId(0L);
                library.setProjectId(0L);
                contentLibraryRepository.save(library);
            }
            map.remove(model.getLibraryUuid());
            syncLibraryItems(model.getItems(), library.getId(), vendorId, managerId);
        }
        for (Map.Entry<String, ContentLibrary> entry : map.entrySet()) {
            Long id = entry.getValue().getId();
            itemRepository.removeByLibraryId(id, managerId);
            contentLibraryRepository.remove(id, managerId);
        }
    }

    public void syncLibraryItems(List<ItemModel> models, Long libraryId, Long vendorId, Long managerId) {
        if (ListTool.isEmpty(models)) {
            itemRepository.removeByLibraryId(libraryId, managerId);
            return;
        }
        List<ContentLibraryItem> items = itemRepository.listByVendorId(vendorId, libraryId);
        Map<String, ContentLibraryItem> map = items.stream()
                .collect(Collectors.toMap(ContentLibraryItem::getItemUuid, Function.identity(), (v1, v2) -> v2));
        for (ItemModel model : models) {
            ContentLibraryItem item = new ContentLibraryItem();
            if (map.containsKey(model.getItemUuid())) {
                item = map.get(model.getItemUuid());
                BeanUtils.copyProperties(model, item);
                item.setMenderId(managerId);
                item.setLibraryId(libraryId);
                itemRepository.update(item);
            } else {
                BeanUtils.copyProperties(model, item);
                item.setCreatorId(managerId);
                item.setGmtCreate(new Date());
                item.setVendorId(vendorId);
                item.setTenantId(0L);
                item.setProjectId(0L);
                item.setLibraryId(libraryId);
                itemRepository.save(item);
            }
            map.remove(model.getItemUuid());
        }
        for (Map.Entry<String, ContentLibraryItem> entry : map.entrySet()) {
            Long id = entry.getValue().getId();
            itemRepository.remove(id, managerId);
        }
    }

}
