package com.bocloud.ims.service.transporter.vendor;

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.common.TaskMsgDriver;
import com.bocloud.cmp.driver.monitor.AlarmDriver;
import com.bocloud.cmp.driver.pbm.PbmProfileDriver;
import com.bocloud.cmp.entity.enums.*;
import com.bocloud.cmp.model.*;
import com.bocloud.cmp.model.contentlibrary.ItemModel;
import com.bocloud.cmp.model.contentlibrary.LibraryModel;
import com.bocloud.cmp.model.pbm.PbmProfileModel;
import com.bocloud.cmp.provider.ButlerRepository;
import com.bocloud.cmp.provider.VmwareProvider;
import com.bocloud.cmp.provider.utils.AssembleTools;
import com.bocloud.common.enums.BoCloudService;
import com.bocloud.common.enums.OSCategory;
import com.bocloud.common.enums.ResourceCatalog;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.Result;
import com.bocloud.common.utils.IDFactory;
import com.bocloud.common.utils.ListTool;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.Ip.IpStatus;
import com.bocloud.ims.entity.resource.contentlibrary.ContentLibrary;
import com.bocloud.ims.entity.resource.contentlibrary.ContentLibraryItem;
import com.bocloud.ims.entity.resource.pbm.PbmProfile;
import com.bocloud.ims.interfaces.resource.IpService;
import com.bocloud.ims.interfaces.scheduler.SnapshotTaskService;
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.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.transporter.ResourceTransporter;
import com.bocloud.ims.service.utils.CmdbInfoConvertor;
import com.bocloud.ims.service.utils.ListUtils;
import com.bocloud.ims.service.utils.SyncVmwareUtils;
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.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
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.Component;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 同步VMware工具类
 *
 * @author weiwei
 */
@Slf4j
@Component
public class VmwareTransporter implements ResourceTransporter {
    private final VdcRepository vdcRepository;
    private final CloudServerRepository cloudServerRepository;
    private final DataStoreRepository dataStoreRepository;
    private final SnapshotRepository snapshotRepository;
    private final NetworkRepository networkRepository;
    private final ClusterRepository clusterRepository;
    private final StoreHostRepository storeHostRepository;
    private final ServerRepository serverRepository;
    private final NetworkCardRepository networkCardRepository;
    private final PortGroupRepository portGroupRepository;
    private final NetworkHostRepository networkHostRepository;
    private final SyncVmwareUtils utils;
    private final ClusterNodeRepository clusterNodeRepository;
    private final ServerConfigRepository serverConfigRepository;
    private final ServerAssetsRepository serverAssetsRepository;
    private final ResourceRepository resourceRepository;
    private final IpRepository ipRepository;
    private final IpPoolRepository ipPoolRepository;
    private final SwitcherRepository switcherRepository;
    private final ImageRepository imageRepository;
    private final ResourcePoolRepository resourcePoolRepository;
    private final IpService ipService;
    private final LocationDriver locationDriver;
    private final PbmProfileDriver profileDriver;
    private final PbmProfileRepository profileRepository;
    private final ScsiLunRepository scsiLunRepository;
    private final IpPoolPortGroupRepository ipPoolPortGroupRepository;
    private final VAppRepository vAppRepository;
    private final ThreadPoolTaskExecutor taskExecutor;
    private final InstanceMessageDispatcher messageDispatcher;
    private final SnapshotTaskService snapshotTaskService;
    private final CloudVendorRepository cloudVendorRepository;
    private final ContentLibraryRepository contentLibraryRepository;
    private final ContentLibraryItemRepository itemRepository;
    private final TaskMsgDriver taskMsgDriver;
    private final TaskMsgRepository taskMsgRepository;
    private final AuthDriver authDriver;
    private final ResourceAlarmRepository alarmRepository;
    private final AlarmDriver alarmDriver;
    private final AmqpTemplate amqpTemplate;
    private final PoolGroupRelationRepository poolGroupRelationRepository;

    @Autowired
    public VmwareTransporter(VdcRepository vdcRepository, CloudServerRepository cloudServerRepository,
                             DataStoreRepository dataStoreRepository, SnapshotRepository snapshotRepository,
                             NetworkRepository networkRepository, ClusterRepository clusterRepository,
                             StoreHostRepository storeHostRepository, ServerRepository serverRepository,
                             NetworkCardRepository networkCardRepository, PortGroupRepository portGroupRepository,
                             NetworkHostRepository networkHostRepository, VolumeRepository volumeRepository,
                             ClusterNodeRepository clusterNodeRepository, ServerConfigRepository serverConfigRepository,
                             ServerAssetsRepository serverAssetsRepository, ResourceRepository resourceRepository,
                             IpRepository ipRepository, IpPoolRepository ipPoolRepository, SwitcherRepository switcherRepository,
                             ImageRepository imageRepository, ResourcePoolRepository resourcePoolRepository, IpService ipService,
                             LocationDriver locationDriver, PbmProfileDriver profileDriver, PbmProfileRepository profileRepository,
                             ScsiLunRepository scsiLunRepository, IpPoolPortGroupRepository ipPoolPortGroupRepository,
                             VAppRepository vAppRepository, ThreadPoolTaskExecutor taskExecutor,
                             InstanceMessageDispatcher messageDispatcher, SnapshotTaskService snapshotTaskService,
                             CloudVendorRepository cloudVendorRepository, ContentLibraryRepository contentLibraryRepository,
                             ContentLibraryItemRepository itemRepository, TaskMsgDriver taskMsgDriver,
                             TaskMsgRepository taskMsgRepository, AuthDriver authDriver, ResourceAlarmRepository alarmRepository,
                             AlarmDriver alarmDriver, AmqpTemplate amqpTemplate, PoolGroupRelationRepository poolGroupRelationRepository) {
        this.amqpTemplate = amqpTemplate;
        this.alarmDriver = alarmDriver;
        this.alarmRepository = alarmRepository;
        this.authDriver = authDriver;
        this.cloudVendorRepository = cloudVendorRepository;
        this.vdcRepository = vdcRepository;
        this.cloudServerRepository = cloudServerRepository;
        this.dataStoreRepository = dataStoreRepository;
        this.snapshotRepository = snapshotRepository;
        this.networkRepository = networkRepository;
        this.clusterRepository = clusterRepository;
        this.storeHostRepository = storeHostRepository;
        this.serverRepository = serverRepository;
        this.networkCardRepository = networkCardRepository;
        this.portGroupRepository = portGroupRepository;
        this.networkHostRepository = networkHostRepository;
        this.clusterNodeRepository = clusterNodeRepository;
        this.serverConfigRepository = serverConfigRepository;
        this.serverAssetsRepository = serverAssetsRepository;
        this.resourceRepository = resourceRepository;
        this.ipRepository = ipRepository;
        this.ipPoolRepository = ipPoolRepository;
        this.switcherRepository = switcherRepository;
        this.imageRepository = imageRepository;
        this.resourcePoolRepository = resourcePoolRepository;
        this.ipService = ipService;
        this.locationDriver = locationDriver;
        this.profileDriver = profileDriver;
        this.profileRepository = profileRepository;
        this.scsiLunRepository = scsiLunRepository;
        this.ipPoolPortGroupRepository = ipPoolPortGroupRepository;
        this.vAppRepository = vAppRepository;
        this.taskExecutor = taskExecutor;
        this.messageDispatcher = messageDispatcher;
        this.snapshotTaskService = snapshotTaskService;
        this.contentLibraryRepository = contentLibraryRepository;
        this.itemRepository = itemRepository;
        this.taskMsgDriver = taskMsgDriver;
        this.taskMsgRepository = taskMsgRepository;
        this.poolGroupRelationRepository = poolGroupRelationRepository;
        this.utils = new SyncVmwareUtils(cloudServerRepository, dataStoreRepository, serverRepository,
                snapshotRepository, networkRepository, clusterRepository, storeHostRepository, networkCardRepository,
                portGroupRepository, networkHostRepository, serverConfigRepository, resourceRepository, ipRepository,
                imageRepository, volumeRepository);
    }

    /**
     * 同步平台实体
     *
     * @param vendor
     * @param operator
     */
    @Override
    public Result transport(CloudVendor vendor, Long operator) {
        CmdbModel model = new CmdbModel();
        model.setUuid(IDFactory.instance().uuid());
        model.setServiceName(BoCloudService.IMS.name());
        model.setManagerId(operator);
        List<CmdbInfo> infos = Lists.newArrayList();
        // 添加云平台数据
        infos.add(CmdbInfoConvertor.getInfo(vendor, null, null, CloudProvider.VMWARE));
        try {
            BocloudResult<?> locationResult = locationDriver.sync(vendor.getUuid());
            Assert.isTrue(locationResult.isSuccess(), "原始数据同步异常！");
            Object data = locationResult.getData();
            if (cloudServerRepository.hasBuilding(vendor.getId())) {
                return new BocloudResult(false, "该平台下有云主机正在创建，请稍后进行同步操作");
            }
            if (snapshotRepository.hasBuilding(vendor.getId())) {
                return new BocloudResult(false, "该平台下有快照正在创建，请稍后进行同步操作");
            }
            // 获取数据库的平台数据
            List<Server> hosts = serverRepository.listByVendor(vendor.getId());
            Map<String, Server> oldHostMap = Maps.newHashMap();
            for (Server host : hosts) {
                oldHostMap.put(host.getUuid() + host.getManageIp(), host);
            }
            List<Vdc> vdcs = vdcRepository.listByVendor(vendor.getId());
            Map<String, Vdc> oldVdcMap = Maps.newHashMap();
            for (Vdc vdc : vdcs) {
                oldVdcMap.put(vdc.getName(), vdc);
            }
            // 获取同步数据
            String content = JSONObject.toJSONString(data);
            List<Vdc> allVdcs = JSONObject.parseArray(content, Vdc.class);
            log.info("Start sync datacenter of vendor[" + vendor.getId() + "]");
            for (Vdc vdc : allVdcs) {
                log.info("数据中心名称：{}，value：{}", vdc.getName(), vdc.getVdcVal());
                Long vdcId = null;
                String vdcGuid = null;
                List<CmdbRelation> relations = Lists.newArrayList();
                relations.add(new CmdbRelation(ModuleCode.VC_VENDOR.name(), 1L, ListUtils.getList(vendor.getGuid())));
                relations.add(new CmdbRelation(ModuleCode.VC_VENDOR.name(), 2L, ListUtils.getList(vendor.getGuid())));
                if (oldVdcMap.containsKey(vdc.getName())) {
                    Vdc oldVdc = oldVdcMap.get(vdc.getName());
                    oldVdc.setMenderId(operator);
                    oldVdc.setCpuTotal(vdc.getCpuTotal());
                    oldVdc.setCpuUsed(vdc.getCpuUsed());
                    oldVdc.setDiskTotal(vdc.getDiskTotal());
                    oldVdc.setDiskUsed(vdc.getDiskUsed());
                    oldVdc.setMemTotal(vdc.getMemTotal());
                    oldVdc.setMemUsed(vdc.getMemUsed());
                    oldVdc.setName(vdc.getName());
                    oldVdc.setType(CloudProvider.VMWARE.name());
                    vdcRepository.update(oldVdc);
                    vdcId = oldVdc.getId();
                    vdcGuid = oldVdc.getGuid();
                    // cmdb添加数据中心数据
                    infos.add(CmdbInfoConvertor.getInfo(oldVdc, null, relations, CloudProvider.VMWARE));
                } else {
                    vdc.preSave(operator, operator, vendor.getId());
                    vdc.setType(CloudProvider.VMWARE.name());
                    vdcRepository.save(vdc);
                    vdcId = vdc.getId();
                    vdcGuid = vdc.getGuid();
                    // cmdb更新数据中心数据
                    infos.add(CmdbInfoConvertor.getInfo(vdc, null, relations, CloudProvider.VMWARE));
                }
                // 从map中移除更新的数据中心
                oldVdcMap.remove(vdc.getName());
                // 同步分布式交换机
                List<Switcher> switchers = switcherRepository.listByVdc(vdcId, "DVSWITCH");
                log.info("Start sync dvswitcher of datacenter[" + vdcId + "]");
                syncSwitcher(switchers, vdc.getSwitchers(), vendor.getId(), vdcId, null, operator, "DVSWITCH", infos,
                        vendor.getGuid());
                // 获取分布式交换机
                Map<String, Long> dvswitchMap = Maps.newHashMap();
                Map<String, Long> dvswitchNameMap = Maps.newHashMap();
                Map<String, String> groupMap = Maps.newHashMap();
                switchers = switcherRepository.listByVdc(vdcId, "DVSWITCH");
                for (Switcher switcher : switchers) {
                    dvswitchMap.put(switcher.getSwitcherVal(), switcher.getId());
                    dvswitchNameMap.put(switcher.getName(), switcher.getId());
                    List<PortGroup> groups = portGroupRepository.listBySwitcher(switcher.getId());
                    for (PortGroup group : groups) {
                        groupMap.put(group.getGroupVal(), switcher.getSwitcherVal());
                    }
                }
                // 同步网络
                List<Network> networks = networkRepository.listByVdc(vdcId);
                Map<String, Network> networkMap = Maps.newHashMap();
                log.info("Start sync network of datacenter[" + vdcId + "]");
                syncNetwork(networks, vdc.getNetworks(), vendor.getId(), vdcId, operator, networkMap, dvswitchMap, infos,
                        vendor.getGuid(), vdcGuid);
                // 同步存储
                Map<String, DataStore> storeMap = new HashMap<>();
                List<DataStore> stores = dataStoreRepository.listByVdc(vdcId);
                log.info("Start sync data store and image of datacenter[" + vdcId + "]");
                syncStore(storeMap, stores, vdc.getStores(), vendor.getId(), vdcId, operator, infos, vendor.getGuid(),
                        vdcGuid);
                final Long finalVdcId = vdcId;
                // 同步数据存储中的镜像文件，由于镜像文件较多，此处做异步处理
                taskExecutor.execute(() -> {
                    BocloudResult<List<DataStoreModel>> result =
                            locationDriver.syncStoreImages(vendor.getUuid(), vdc.getName());
                    Map<String, DataStoreModel> dataStoreMap = new HashMap<>();
                    if (result.isSuccess()) {
                        List<DataStoreModel> storeModels = result.getData();
                        for (DataStoreModel storeModel : storeModels) {
                            dataStoreMap.put(storeModel.getStoreVal(), storeModel);
                        }
                    }
                    try {
                        List<DataStore> dataStores = dataStoreRepository.listByVdc(finalVdcId);
                        for (DataStore dataStore : dataStores) {
                            Long storeId = dataStore.getId();
                            List<Image> oldImages = imageRepository.listByStoreId(storeId);
                            DataStoreModel storeModel = dataStoreMap.get(dataStore.getStoreVal());
                            if (null != storeModel) {
                                List<ImageModel> imageModels = storeModel.getImages();
                                List<Image> newImages = new ArrayList<>();
                                if (!ListTool.isEmpty(imageModels)) {
                                    newImages =
                                            JSONArray.parseArray(JSONArray.toJSONString(imageModels), Image.class);
                                }
                                this.syncImage(oldImages, newImages, storeId, vendor.getId(), operator);
                            }
                        }
                    } catch (Exception e) {
                        log.error("获取数据存储镜像失败：", e);
                    }
                });
                // 查询当前云平台下数据库已存在的云主机数据
                List<CloudServer> oldServers = cloudServerRepository.listByVdcId(vdcId);
                Map<String, CloudServer> oldServerMap = Maps.newHashMap();
                for (CloudServer server : oldServers) {
//                        if (StringUtils.isEmpty(server.getInstanceId())) {
//                            oldServerMap.put(server.getName(), server);
//                        } else {
//                            oldServerMap.put(server.getInstanceId(), server);
//                        }
                    // 如果instanceId为空则直接删除，防止数据库产生脏数据  后续有问题在调整 fix bug #PBSM-12649
                    if (oldServerMap.containsKey(server.getInstanceId()) || StringUtils.isEmpty(server.getInstanceId())) {
                        cloudServerRepository.remove(server.getId(), operator);
                    } else {
                        oldServerMap.put(server.getInstanceId(), server);
                    }
                }
                // 同步宿主机
                List<HostSystem> newHostSystems = vdc.getHosts();
                if (!ListTool.isEmpty(newHostSystems)) {
                    log.info("Start sync host of datacenter[" + vdcId + "]");
                    syncHost(storeMap, newHostSystems, oldHostMap, vendor.getId(), vdcId, null, operator, networkMap,
                            groupMap, vendor.getType(), infos, vendor.getGuid(), vdcGuid, null, oldServerMap,
                            dvswitchNameMap);
                }
                // 同步集群
                List<Cluster> clusters = clusterRepository.listByVdc(vdcId);
                log.info("Start sync cluster of datacenter[" + vdcId + "]");
                syncCluster(clusters, vdc.getClusters(), vendor.getId(), vdcId, operator, storeMap, oldHostMap,
                        networkMap, groupMap, vendor.getType(), infos, vendor.getGuid(), vdcGuid, oldServerMap,
                        dvswitchNameMap);
                // 删除当前云平台下不存在的云主机相关数据
                for (CloudServer removeServer : oldServerMap.values()) {
                    removeServerCascade(removeServer, operator, vendor.getId());
                    // cmdb删除云主机数据
                    infos.add(CmdbInfoConvertor.getInfo(removeServer, "delete", null, CloudProvider.VMWARE));
                }
                // 同步资源池
                List<VmResourcePool> pools = resourcePoolRepository.listByVdc(vdcId);
                log.info("Start sync resource pool of datacenter[" + vdcId + "]");
                syncResourcePool(pools, vdc.getPools(), vdcId, vendor.getId(), operator);
                // 同步云主机所在资源池信息
                log.info("Start sync resource pool of datacenter[" + vdcId + "]");
                if (!ListTool.isEmpty(newHostSystems)) {
                    for (HostSystem host : newHostSystems) {
                        syncServerResPool(
                                JSONArray.parseArray(JSONObject.toJSONString(host.getServers()), CloudServer.class),
                                vdcId);
                    }
                }
                List<Cluster> newClusters = vdc.getClusters();
                if (!ListTool.isEmpty(newClusters)) {
                    for (Cluster cluster : newClusters) {
                        List<HostSystem> clusterHosts = cluster.getHosts();
                        if (!ListTool.isEmpty(clusterHosts)) {
                            for (HostSystem host : clusterHosts) {
                                syncServerResPool(JSONArray.parseArray(JSONObject.toJSONString(host.getServers()),
                                        CloudServer.class), vdcId);
                            }
                        }
                    }
                }
                log.info("End sync resource pool of datacenter[" + vdcId + "]");
                // 同步vapp
                log.info("Start sync vapp of datacenter[" + vdcId + "]");
                List<VApp> oldVapps = vAppRepository.listByVdc(vdcId);
                syncVapp(oldVapps, vdc.getVapps(), vdcId, vendor.getId(), operator);
                log.info("End sync vapp of datacenter[" + vdcId + "]");
                log.info("End sync vapp of datacenter[" + vdcId + "]");
                syncVappVmRelation(finalVdcId, operator);
            }
            // 同步数据中心，删除不存在的数据中心
            log.info("Remove data centers that does not exists");
            syncVdc(oldVdcMap, operator, infos);
            // 同步宿主机，删除不存在的宿主机
            log.info("Remove hosts that does not exists");
            removeHost(oldHostMap, operator, infos);
            // 6.0以下不支持vcenter存储策略
            if (!"6.0".equals(vendor.getVersion()) && !"5.5".equals(vendor.getVersion())) {
                // 同步存储策略
                BocloudResult result = profileDriver.list(vendor.getUuid());
                if (result.isSuccess()) {
                    log.info("Start sync vcenter pbm profile");
                    List<PbmProfileModel> profileModels =
                            JSONArray.parseArray(JSONObject.toJSONString(result.getData()), PbmProfileModel.class);
                    syncPbmProfile(profileModels, vendor.getId());
                    log.info("End sync vcenter pbm profile");
                }
            }
            // 删除IP表中不存在的脏数据
            ipService.processRubbishIp(vendor.getId());
            model.setData(infos);
            // 发送消息到cmdb模块，进行数据同步
            messageDispatcher.cacheMessage(JSONObject.toJSONString(model));

            new Thread(() -> {
                // 同步内容库
                this.syncContentLibraries(vendor.getId(), operator);
                // 同步历史平台任务
                this.syncContentVendorTaskMsg(vendor.getId());
            }).start();
            this.syncAlarm(vendor, operator);

            return new BocloudResult(true, "云平台【 " + vendor.getName() + " 】数据同步成功");
        } catch (Exception e) {
            log.error("Sync error:", e);
            return new BocloudResult(false, "云平台【 " + vendor.getName() + " 】数据同步失败:" + e.getMessage());
        }
    }

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

    public BocloudResult syncContentVendorTaskMsg(Long vendorId) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Assert.notNull(vendor, "云平台不存在");
            BocloudResult<List<TaskMsgModel>> result = taskMsgDriver.historyList(vendor.getUuid());
            if (result.isSuccess() && null != result.getData()) {
                log.info("Start sync VendorTaskMsg ");
                syncVendorTaskMsg(result.getData(), vendorId);
                log.info("End sync VendorTaskMsg ");
            }
            if (result.isFailed()) {
                return new BocloudResult(false, "平台历史任务同步失败:" + result.getMessage());
            }
            return new BocloudResult(true, "平台历史任务同步成功");
        } catch (Exception e) {
            log.error("Get error message:{}", e);
            return new BocloudResult(false, "平台历史任务同步失败:" + e.getMessage());
        }
    }

    public void syncVendorTaskMsg(List<TaskMsgModel> models, Long vendorId) {
        if (ListTool.isEmpty(models)) {
            return;
        }
        //查询平台现有历史任务
        List<VendorTaskMsg> vendorTaskMsgOld = taskMsgRepository.listByVendorId(vendorId);
        List<VendorTaskMsg> vendorTaskMsgNew = Lists.newArrayList();
        Map<String, VendorTaskMsg> vendorTaskMsgMap = Maps.newHashMap();
        if (!ListTool.isEmpty(vendorTaskMsgOld)) {
            vendorTaskMsgMap = vendorTaskMsgOld.stream().collect(Collectors.toMap(VendorTaskMsg::getKey, Function.identity(), (key1, key2) -> key2));
        }
        //未执行完成的任务
        Map<String, VendorTaskMsg> runningTaskMsg = vendorTaskMsgOld.stream().filter(vendorTaskMsg -> null == vendorTaskMsg.getCompleteTime()).collect(Collectors.toMap(VendorTaskMsg::getKey, Function.identity(),
                (key1, key2) -> key2));
        for (TaskMsgModel taskMsgMode : models) {
            //历史数据不存在
            if (null == vendorTaskMsgMap.get(taskMsgMode.getKey())) {
                VendorTaskMsg vendorTaskMsg = new VendorTaskMsg();
                BeanUtils.copyProperties(taskMsgMode, vendorTaskMsg);
                vendorTaskMsg.setVendorId(vendorId);
                vendorTaskMsgNew.add(vendorTaskMsg);
            }
            //处理未执行完成的任务,设置结束时间及执行时间
            if (!runningTaskMsg.isEmpty() && runningTaskMsg.size() != 0) {
                if (runningTaskMsg.containsKey(taskMsgMode.getKey())) {
                    VendorTaskMsg vendorTaskMsg = runningTaskMsg.get(taskMsgMode.getKey());
                    BeanUtils.copyProperties(taskMsgMode, vendorTaskMsg);
                    taskMsgRepository.update(vendorTaskMsg);
                }
            }
        }
        if (!ListTool.isEmpty(vendorTaskMsgNew)) {
            taskMsgRepository.batchSave(vendorTaskMsgNew, vendorTaskMsgNew.size());
        }
    }

    public BocloudResult syncContentLibraries(Long vendorId, Long operator) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Assert.notNull(vendor, "云平台不存在");
            BocloudResult<List<LibraryModel>> result = locationDriver.listLibraries(vendor.getUuid());
            if (result.isSuccess() && null != result.getData()) {
                log.info("Start sync content library and items");
                syncLibraries(result.getData(), vendorId, operator);
                log.info("End sync content library and items");
            }
            return new BocloudResult(true, "内容库同步成功");
        } catch (Exception e) {
            log.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);
        }
    }


    private void syncVappVmRelation(Long vdcId, Long operator) throws Exception {
        List<VApp> vapps = vAppRepository.listByVdc(vdcId);
        Map<String, Long> vappVmMap = new HashMap<>();
        for (VApp vapp : vapps) {
            if (StringUtils.isEmpty(vapp.getVmInstanceIds())) {
                continue;
            }
            List<String> instanceIds = JSONArray.parseArray(vapp.getVmInstanceIds(), String.class);
            if (ListTool.isEmpty(instanceIds)) {
                continue;
            }
            for (String instanceId : instanceIds) {
                vappVmMap.put(instanceId, vapp.getId());
            }
        }
        List<CloudServer> servers = cloudServerRepository.listByVdcId(vdcId);
        Map<String, CloudServer> vmMap = servers.stream().filter(vm -> !StringUtils.isEmpty(vm.getInstanceId()))
                .collect(Collectors.toMap(CloudServer::getInstanceId,Function.identity(), (f, s)->{
                    long ftime = f.getGmtCreate() == null ? 0 : f.getGmtCreate().getTime();
                    long stime = s.getGmtCreate() == null ? 0 : s.getGmtCreate().getTime();
                    return ftime > stime ? f : s;
                }));
        List<CloudServer> updateServers = new ArrayList<>();
        for (String key : vmMap.keySet()) {
            Long vappId = vappVmMap.get(key);
            if (null != vappId) {
                CloudServer server = vmMap.get(key);
                if (null != server) {
                    server.setMenderId(operator);
                    server.setVappId(vappId);
                    server.setGmtModify(new Date());
                    updateServers.add(server);
                }
            }
        }
        if (!ListTool.isEmpty(updateServers)) {
            cloudServerRepository.batchUpdate(updateServers, 1000);
        }
    }

    /**
     * 同步scsi lun
     *
     * @param models
     * @param vendorId
     * @param hostId
     * @throws Exception
     */
    private void syncScsiLun(List<ScsiLunModel> models, Long vendorId, Long hostId) throws Exception {
        if (ListTool.isEmpty(models)) {
            scsiLunRepository.removeByHostId(hostId);
            return;
        }
        List<ScsiLun> luns = scsiLunRepository.listByVendorId(vendorId);
        Map<String, ScsiLun> lunMap = new HashMap<>();
        for (ScsiLun lun : luns) {
            if (lunMap.containsKey(lun.getUuid())) {
                profileRepository.remove(lun.getId());
            } else {
                lunMap.put(lun.getUuid(), lun);
            }
        }
        for (ScsiLunModel model : models) {
            ScsiLun lun = new ScsiLun();
            if (lunMap.containsKey(model.getUuid())) {
                lun = lunMap.get(model.getUuid());
                BeanUtils.copyProperties(model, lun);
                scsiLunRepository.update(lun);
                lunMap.remove(model.getUuid());
                continue;
            }
            BeanUtils.copyProperties(model, lun);
            lun.setVendorId(vendorId);
            lun.setHostId(hostId);
            scsiLunRepository.save(lun);
            lunMap.remove(model.getUuid());
        }
        for (Entry<String, ScsiLun> entry : lunMap.entrySet()) {
            scsiLunRepository.remove(entry.getValue().getId());
        }
    }

    /**
     * 同步vcenter存储策略
     *
     * @param models
     * @param vendorId
     * @throws Exception
     */
    public void syncPbmProfile(List<PbmProfileModel> models, Long vendorId) throws Exception {
        if (ListTool.isEmpty(models)) {
            profileRepository.removeByVendorId(vendorId);
            return;
        }
        List<PbmProfile> profiles = profileRepository.listByVendorId(vendorId);
        Map<String, PbmProfile> profileMap = new HashMap<>();
        for (PbmProfile profile : profiles) {
            if (profileMap.containsKey(profile.getProfileId())) {
                profileRepository.remove(profile.getId());
            } else {
                profileMap.put(profile.getProfileId(), profile);
            }
        }
        for (PbmProfileModel model : models) {
            PbmProfile profile = new PbmProfile();
            if (profileMap.containsKey(model.getProfileId())) {
                profile = profileMap.get(model.getProfileId());
                BeanUtils.copyProperties(model, profile);
                profileRepository.update(profile);
                profileMap.remove(model.getProfileId());
                continue;
            }
            BeanUtils.copyProperties(model, profile);
            profile.setVendorId(vendorId);
            profileRepository.save(profile);
            profileMap.remove(model.getProfileId());
        }
        for (Entry<String, PbmProfile> entry : profileMap.entrySet()) {
            profileRepository.remove(entry.getValue().getId());
        }
    }

    /**
     * 同步云主机所在资源池信息
     */
    private void syncServerResPool(List<CloudServer> cloudServers, Long vdcId) throws Exception {
        for (CloudServer cloudServer : cloudServers) {
            CloudServer server = cloudServerRepository.getByInstanceId(cloudServer.getInstanceId());
            VmResourcePool vmResourcePool = resourcePoolRepository.queryByPoolVal(cloudServer.getResPoolVal(), vdcId);
            if (null != vmResourcePool && null != server) {
                server.setResPoolId(vmResourcePool.getId());
                cloudServerRepository.update(server);
            } else if (null == vmResourcePool && null != server) {
                server.setResPoolId(0L);
                cloudServerRepository.update(server);
            }
        }
    }

    /**
     * 同步vapp
     *
     * @param oldVapps
     * @param newVapps
     * @param vdcId
     * @param vendorId
     * @param operator
     * @throws Exception
     */
    public void syncVapp(List<VApp> oldVapps, List<VApp> newVapps, Long vdcId, Long vendorId, Long operator)
            throws Exception {
        if (!ListTool.isEmpty(oldVapps) && ListTool.isEmpty(newVapps)) {
            vAppRepository.removeByVdc(vdcId, operator);
        } else if (!ListTool.isEmpty(oldVapps) && !ListTool.isEmpty(newVapps)) {
            List<Server> servers = serverRepository.listByVdc(vdcId);
            Map<String, Long> serverMap = servers.stream().collect(Collectors.toMap(Server::getName, Server::getId));
            List<Cluster> clusters = clusterRepository.listByVdc(vdcId);
            Map<String, Long> clusterMap =
                    clusters.stream().collect(Collectors.toMap(Cluster::getClusterVal, Cluster::getId, (v1, v2) -> v1));
            List<VmResourcePool> pools = resourcePoolRepository.listByVdc(vdcId);
            Map<String, Long> poolMap = pools.stream()
                    .collect(Collectors.toMap(VmResourcePool::getPoolVal, VmResourcePool::getId, (v1, v2) -> v1));
            Map<String, VApp> oldMap = new HashMap<>();
            for (VApp oldVapp : oldVapps) {
                oldMap.put(oldVapp.getVappVal(), oldVapp);
            }
            for (VApp newVapp : newVapps) {
                // 更新vapp
                if (oldMap.containsKey(newVapp.getVappVal())) {
                    VApp vapp = oldMap.get(newVapp.getVappVal());
                    vapp.setName(newVapp.getName());
                    vapp.setConfig(newVapp.getConfig());
                    vapp.setTargetCategory(newVapp.getTargetCategory());
                    vapp.setTargetVal(newVapp.getTargetVal());
                    if (!StringUtils.isEmpty(newVapp.getHostName())) {
                        vapp.setTargetId(serverMap.get(newVapp.getHostName()));
                    } else {
                        vapp.setTargetId(clusterMap.get(newVapp.getTargetVal()));
                    }
                    vapp.setParentVal(newVapp.getParentVal());
                    vapp.setVappVal(newVapp.getVappVal());
                    vapp.setPoolId(poolMap.get(newVapp.getPoolVal()));
                    vapp.setPoolVal(newVapp.getPoolVal());
                    vapp.setSummary(newVapp.getSummary());
                    vapp.setVappConfig(newVapp.getVappConfig());
                    vapp.setVmInstanceIds(newVapp.getVmInstanceIds());
                    vapp.setTags(newVapp.getTags());
                    vapp.setMenderId(operator);
                    vAppRepository.update(vapp);
                } else {
                    if (!StringUtils.isEmpty(newVapp.getHostName())) {
                        newVapp.setTargetId(serverMap.get(newVapp.getHostName()));
                    } else {
                        newVapp.setTargetId(clusterMap.get(newVapp.getTargetVal()));
                    }
                    newVapp.setPoolId(poolMap.get(newVapp.getPoolVal()));
                    newVapp.setVendorId(vendorId);
                    newVapp.setVdcId(vdcId);
                    newVapp.setCreatorId(operator);
                    vAppRepository.save(newVapp);
                }
                oldMap.remove(newVapp.getVappVal());
            }
            Iterator<VApp> vapps = oldMap.values().iterator();
            while (vapps.hasNext()) {
                vAppRepository.remove(vapps.next().getId(), operator);
            }
            // 处理上下级vapp关系
            List<VApp> vappList = vAppRepository.listByVdc(vdcId);
            Map<String, VApp> vappMap = new HashMap<String, VApp>();
            for (VApp vApp : vappList) {
                vappMap.put(vApp.getVappVal(), vApp);
            }
            for (VApp vapp : vappList) {
                vapp.setParentId(0L);
                if (vappMap.containsKey(vapp.getParentVal())) {
                    VApp app = vappMap.get(vapp.getParentVal());
                    if (null != app) {
                        vapp.setParentId(app.getId());
                        vapp.setPoolId(app.getPoolId());
                    }
                }
                vapp.setMenderId(operator);
                vAppRepository.update(vapp);
            }
        } else if (ListTool.isEmpty(oldVapps) && !ListTool.isEmpty(newVapps)) {
            List<Server> servers = serverRepository.listByVdc(vdcId);
            Map<String, Long> serverMap = servers.stream().collect(Collectors.toMap(Server::getName, Server::getId));
            List<Cluster> clusters = clusterRepository.listByVdc(vdcId);
            Map<String, Long> clusterMap =
                    clusters.stream().collect(Collectors.toMap(Cluster::getClusterVal, Cluster::getId));
            List<VmResourcePool> pools = resourcePoolRepository.listByVdc(vdcId);
            Map<String, Long> poolMap =
                    pools.stream().collect(Collectors.toMap(VmResourcePool::getPoolVal, VmResourcePool::getId));
            for (VApp vapp : newVapps) {
                if (!StringUtils.isEmpty(vapp.getHostName())) {
                    vapp.setTargetId(serverMap.get(vapp.getHostName()));
                } else {
                    vapp.setTargetId(clusterMap.get(vapp.getTargetVal()));
                }
                vapp.setPoolId(poolMap.get(vapp.getPoolVal()));
                vapp.setVendorId(vendorId);
                vapp.setVdcId(vdcId);
                vapp.setCreatorId(operator);
                vAppRepository.save(vapp);
            }
            // 处理上下级vapp关系
            List<VApp> vappList = vAppRepository.listByVdc(vdcId);
            Map<String, VApp> vappMap = new HashMap<String, VApp>();
            for (VApp vApp : vappList) {
                vappMap.put(vApp.getVappVal(), vApp);
            }
            for (VApp vapp : vappList) {
                vapp.setParentId(0L);
                if (vappMap.containsKey(vapp.getParentVal())) {
                    VApp app = vappMap.get(vapp.getParentVal());
                    if (null != app) {
                        vapp.setParentId(app.getId());
                        vapp.setPoolId(app.getPoolId());
                    }
                }
                vapp.setMenderId(operator);
                vAppRepository.update(vapp);
            }
        }
    }

    public void syncResourcePool(List<VmResourcePool> oldPools, List<VmResourcePool> newPools, Long vdcId,
                                 Long vendorId, Long operator) throws Exception {
        if (!ListTool.isEmpty(oldPools) && ListTool.isEmpty(newPools)) {
            resourcePoolRepository.removeByVdc(vdcId, operator);
        } else if (!ListTool.isEmpty(oldPools) && !ListTool.isEmpty(newPools)) {
            Map<String, VmResourcePool> oldMap = Maps.newHashMap();
            for (VmResourcePool oldPool : oldPools) {
                oldMap.put(oldPool.getPoolVal(), oldPool);
            }
            for (VmResourcePool newPool : newPools) {
                // 更新资源池
                if (oldMap.containsKey(newPool.getPoolVal())) {
                    VmResourcePool pool = oldMap.get(newPool.getPoolVal());
                    pool.setName(newPool.getName());
                    pool.setCpuReservation(newPool.getCpuReservation());
                    pool.setCpuExpanReservation(newPool.getCpuExpanReservation());
                    pool.setCpuLimit(newPool.getCpuLimit());
                    pool.setCpuShares(newPool.getCpuShares());
                    pool.setCpuShareLevel(newPool.getCpuShareLevel());
                    pool.setMemReservation(newPool.getMemReservation());
                    pool.setMemExpanReservation(newPool.getCpuExpanReservation());
                    pool.setMemLimit(newPool.getMemLimit());
                    pool.setMemShares(newPool.getMemShares());
                    pool.setMemShareLevel(newPool.getMemShareLevel());
                    pool.setMenderId(operator);
                    // 资源池所属
                    Long owner = null;
                    // 所属为集群
                    if ("CLUSTER".equals(newPool.getOwnerCategory())) {
                        Cluster cluster = clusterRepository.queryByClusterVal(newPool.getClusterVal(), vdcId);
                        if (null != cluster) {
                            owner = cluster.getId();
                        }
                    } else if ("HOST".equals(newPool.getOwnerCategory())) {
                        // 所属为宿主机
                        Server server = serverRepository.getByName(newPool.getHostName(), vendorId);
                        if (null != server) {
                            owner = server.getId();
                        }
                    }
                    pool.setOwner(owner);
                    resourcePoolRepository.update(pool);
                    oldMap.remove(newPool.getPoolVal());
                } else {
                    // 是否为一级资源池
                    if (StringUtils.isEmpty(newPool.getParentName())) {
                        newPool.setParentId(0L);
                    } else {
                        // 查询父资源池
                        VmResourcePool parent =
                                resourcePoolRepository.queryByPoolVal(newPool.getParentPoolVal(), vdcId);
                        if (null != parent) {
                            newPool.setParentId(parent.getId());
                        }
                    }
                    newPool.setVdcId(vdcId);
                    newPool.setVendorId(vendorId);
                    // 资源池所属
                    Long owner = null;
                    // 所属为集群
                    if ("CLUSTER".equals(newPool.getOwnerCategory())) {
                        Cluster cluster = clusterRepository.queryByClusterVal(newPool.getClusterVal(), vdcId);
                        if (null != cluster) {
                            owner = cluster.getId();
                        }
                    } else if ("HOST".equals(newPool.getOwnerCategory())) {
                        // 所属为宿主机
                        Server server = serverRepository.getByName(newPool.getHostName(), vendorId);
                        if (null != server) {
                            owner = server.getId();
                        }
                    }
                    newPool.setOwner(owner);
                    newPool.preSave(operator, operator, vendorId, 0L);
                    resourcePoolRepository.save(newPool);
                    oldMap.remove(newPool.getPoolVal());
                }
            }
            Iterator<VmResourcePool> pools = oldMap.values().iterator();
            while (pools.hasNext()) {
                resourcePoolRepository.remove(pools.next().getId(), operator);
            }
        } else if (ListTool.isEmpty(oldPools) && !ListTool.isEmpty(newPools)) {
            for (VmResourcePool newPool : newPools) {
                // 是否为一级资源池
                if (StringUtils.isEmpty(newPool.getParentName())) {
                    newPool.setParentId(0L);
                } else {
                    // 查询父资源池
                    VmResourcePool parent = resourcePoolRepository.queryByPoolVal(newPool.getParentPoolVal(), vdcId);
                    if (null != parent) {
                        newPool.setParentId(parent.getId());
                    }
                }
                // 数据中心
                newPool.setVdcId(vdcId);
                // 云平台
                newPool.setVendorId(vendorId);
                // 资源池所属
                Long owner = null;
                // 所属为集群
                if ("CLUSTER".equals(newPool.getOwnerCategory())) {
                    Cluster cluster = clusterRepository.queryByClusterVal(newPool.getClusterVal(), vdcId);
                    if (null != cluster) {
                        owner = cluster.getId();
                    }
                } else if ("HOST".equals(newPool.getOwnerCategory())) {
                    // 所属为宿主机
                    Server server = serverRepository.getByName(newPool.getHostName(), vendorId);
                    if (null != server) {
                        owner = server.getId();
                    }
                }
                newPool.setOwner(owner);
                newPool.preSave(operator, operator, vendorId, 0L);
                resourcePoolRepository.save(newPool);
            }
        }
    }

    public void syncSwitcher(List<Switcher> oldSwitchers, List<Switcher> newSwitchers, Long vendorId, Long vdcId,
                             Long hostId, Long operator, String type, List<CmdbInfo> infos, String vendorGuid) throws Exception {
        if (!ListTool.isEmpty(oldSwitchers) && ListTool.isEmpty(newSwitchers)) {
            for (Switcher switcher : oldSwitchers) {
                // cmdb删除云主机数据
                infos.add(CmdbInfoConvertor.getInfo(switcher, "delete", null, CloudProvider.VMWARE));
                networkCardRepository.release(switcher.getId(), operator);
                portGroupRepository.removeBySwitcher(switcher.getId(), operator);
            }
            if ("DVSWITCH".equals(type)) {
                switcherRepository.removeByVdc(vdcId, "DVSWITCH", operator);
            } else {
                switcherRepository.removeByHostId(hostId, operator);
            }
        } else {
            Map<String, Switcher> oldMap = Maps.newHashMap();
            for (Switcher switcher : oldSwitchers) {
                oldMap.put(switcher.getSwitcherVal(), switcher);
            }
            for (Switcher switcher : newSwitchers) {
                // 云主机与对象的关系
                List<CmdbRelation> relations = Lists.newArrayList();
                relations.add(new CmdbRelation(ModuleCode.VC_VENDOR.name(), 2L, ListUtils.getList(vendorGuid)));
                String switcherGuid = null;
                Long switcherId = null;
                if (oldMap.containsKey(switcher.getSwitcherVal())) {
                    Switcher oldSwitcher = oldMap.get(switcher.getSwitcherVal());
                    switcher.setId(oldSwitcher.getId());
                    switcher.setGmtCreate(oldSwitcher.getGmtCreate());
                    switcher.setGmtModify(new Date());
                    switcher.setCreatorId(oldSwitcher.getCreatorId());
                    switcher.setMenderId(operator);
                    switcher.setDeleted(oldSwitcher.getDeleted());
                    switcher.setHostId(oldSwitcher.getHostId());
                    switcher.setVendorId(vendorId);
                    switcher.setVdcId(vdcId);
                    BeanUtils.copyProperties(switcher, oldSwitcher, "guid");
                    if (StringUtils.isEmpty(oldSwitcher.getGuid())) {
                        oldSwitcher.setGuid(IDFactory.instance().uuid());
                    }
                    switcherRepository.update(oldSwitcher);
                    switcherGuid = oldSwitcher.getGuid();
                    switcherId = oldSwitcher.getId();
                    // 移除存在更新的交换机
                    oldMap.remove(switcher.getSwitcherVal());
                    infos.add(CmdbInfoConvertor.getInfo(oldSwitcher, null, relations, CloudProvider.VMWARE));
                } else {
                    switcher.preSave(operator, operator, vendorId, vdcId, hostId);
                    switcherRepository.save(switcher);
                    switcherGuid = switcher.getGuid();
                    switcherId = switcher.getId();
                    infos.add(CmdbInfoConvertor.getInfo(switcher, null, relations, CloudProvider.VMWARE));
                }
                // 同步该交换机下的端口组
                List<PortGroup> groups = portGroupRepository.listBySwitcher(switcherId);
                syncPortGroup(groups, switcher.getGroups(), vendorId, switcherId, operator, switcher.getType(), infos,
                        switcherGuid);
            }
            // 删除不存在的交换机
            Iterator<Switcher> switchers = oldMap.values().iterator();
            while (switchers.hasNext()) {
                Switcher switcher = switchers.next();
                Long switcherId = switcher.getId();
                // cmdb删除云主机数据
                infos.add(CmdbInfoConvertor.getInfo(switcher, "delete", null, CloudProvider.VMWARE));
                networkCardRepository.release(switcherId, operator);
                portGroupRepository.removeBySwitcher(switcherId, operator);
                switcherRepository.remove(switcherId, operator);
            }
        }
    }

    private void syncPortGroup(List<PortGroup> oldGroups, List<PortGroup> newGroups, Long vendorId, Long switcherId,
                               Long operator, String switchType, List<CmdbInfo> infos, String switcherGuid) throws Exception {
        if (!ListTool.isEmpty(oldGroups) && ListTool.isEmpty(newGroups)) {
            List<PortGroup> groups = portGroupRepository.listBySwitcher(switcherId);
            for (PortGroup group : groups) {
                // cmdb删除云主机数据
                infos.add(CmdbInfoConvertor.getInfo(group, "delete", null, CloudProvider.VMWARE));
                ipPoolPortGroupRepository.deleteByGroupId(group.getId());
            }
            portGroupRepository.removeBySwitcher(switcherId, operator);
        } else if (!ListTool.isEmpty(oldGroups) && !ListTool.isEmpty(newGroups)) {
            switch (NetworkType.SwitchType.valueOf(switchType)) {
                case VSWITCH:
                    // 该标准交换机下的端口组
                    Map<String, PortGroup> oldVswitchMap = Maps.newHashMap();
                    for (PortGroup group : oldGroups) {
                        oldVswitchMap.put(group.getName(), group);
                    }
                    for (PortGroup group : newGroups) {
                        // 云主机与对象的关系
                        List<CmdbRelation> relations = Lists.newArrayList();
                        relations
                                .add(new CmdbRelation(ModuleCode.VC_SWITCH.name(), 2L, ListUtils.getList(switcherGuid)));
                        if (oldVswitchMap.containsKey(group.getName())) {
                            PortGroup oldGroup = oldVswitchMap.get(group.getName());
                            group.setId(oldGroup.getId());
                            group.setGmtCreate(oldGroup.getGmtCreate());
                            group.setGmtModify(new Date());
                            group.setCreatorId(oldGroup.getCreatorId());
                            group.setMenderId(operator);
                            group.setVendorId(vendorId);
                            group.setSwitcherId(oldGroup.getSwitcherId());
                            group.setType(oldGroup.getType());
                            group.setDeleted(oldGroup.getDeleted());
                            BeanUtils.copyProperties(group, oldGroup, "guid");
                            if (StringUtils.isEmpty(oldGroup.getGuid())) {
                                oldGroup.setGuid(IDFactory.instance().uuid());
                            }
                            portGroupRepository.update(oldGroup);
                            oldVswitchMap.remove(group.getName());
                            infos.add(CmdbInfoConvertor.getInfo(oldGroup, null, relations, CloudProvider.VMWARE));
                        } else {
                            group.preSave(operator, operator, vendorId, switcherId);
                            portGroupRepository.save(group);
                            infos.add(CmdbInfoConvertor.getInfo(group, null, relations, CloudProvider.VMWARE));
                        }
                    }
                    // 删除不存在的端口组
                    Iterator<PortGroup> vswitchGroups = oldVswitchMap.values().iterator();
                    while (vswitchGroups.hasNext()) {
                        PortGroup group = vswitchGroups.next();
                        // cmdb删除云主机数据
                        infos.add(CmdbInfoConvertor.getInfo(group, "delete", null, CloudProvider.VMWARE));
                        portGroupRepository.remove(group.getId(), operator);
                        ipPoolPortGroupRepository.deleteByGroupId(group.getId());
                    }
                    break;
                case DVSWITCH:
                    Map<String, PortGroup> oldDvswitchMap = Maps.newHashMap();
                    for (PortGroup group : oldGroups) {
                        oldDvswitchMap.put(group.getGroupVal(), group);
                    }
                    for (PortGroup group : newGroups) {
                        // 云主机与对象的关系
                        List<CmdbRelation> relations = Lists.newArrayList();
                        relations
                                .add(new CmdbRelation(ModuleCode.VC_SWITCH.name(), 2L, ListUtils.getList(switcherGuid)));
                        if (oldDvswitchMap.containsKey(group.getGroupVal())) {
                            PortGroup oldGroup = oldDvswitchMap.get(group.getGroupVal());
                            group.setId(oldGroup.getId());
                            group.setGmtCreate(oldGroup.getGmtCreate());
                            group.setGmtModify(new Date());
                            group.setCreatorId(oldGroup.getCreatorId());
                            group.setMenderId(operator);
                            group.setVendorId(vendorId);
                            group.setSwitcherId(oldGroup.getSwitcherId());
                            group.setType(oldGroup.getType());
                            group.setDeleted(oldGroup.getDeleted());
                            BeanUtils.copyProperties(group, oldGroup, "guid");
                            if (StringUtils.isEmpty(oldGroup.getGuid())) {
                                oldGroup.setGuid(IDFactory.instance().uuid());
                            }
                            portGroupRepository.update(oldGroup);
                            // 移除存在更新的端口组
                            oldDvswitchMap.remove(group.getGroupVal());
                            infos.add(CmdbInfoConvertor.getInfo(oldGroup, null, relations, CloudProvider.VMWARE));
                        } else {
                            group.preSave(operator, operator, vendorId, switcherId);
                            portGroupRepository.save(group);
                            infos.add(CmdbInfoConvertor.getInfo(group, null, relations, CloudProvider.VMWARE));
                        }
                    }
                    // 删除不存在的端口组
                    Iterator<PortGroup> dvswitchGroups = oldDvswitchMap.values().iterator();
                    while (dvswitchGroups.hasNext()) {
                        PortGroup group = dvswitchGroups.next();
                        // cmdb删除云主机数据
                        infos.add(CmdbInfoConvertor.getInfo(group, "delete", null, CloudProvider.VMWARE));
                        portGroupRepository.remove(group.getId(), operator);
                        ipPoolPortGroupRepository.deleteByGroupId(group.getId());
                    }
                    break;
                default:
                    break;
            }
        } else if (ListTool.isEmpty(oldGroups) && !ListTool.isEmpty(newGroups)) {
            for (PortGroup group : newGroups) {
                // 云主机与对象的关系
                List<CmdbRelation> relations = Lists.newArrayList();
                relations.add(new CmdbRelation(ModuleCode.VC_SWITCH.name(), 2L, ListUtils.getList(switcherGuid)));
                group.preSave(operator, operator, vendorId, switcherId);
                portGroupRepository.save(group);
                infos.add(CmdbInfoConvertor.getInfo(group, null, relations, CloudProvider.VMWARE));
            }
        }
    }

    /**
     * 同步数据中心(删除)
     *
     * @param oldVdcMap
     * @param operator
     * @param infos
     * @throws Exception
     */
    private void syncVdc(Map<String, Vdc> oldVdcMap, Long operator, List<CmdbInfo> infos) throws Exception {
        Iterator<Vdc> vdcs = oldVdcMap.values().iterator();
        while (vdcs.hasNext()) {
            Vdc vdc = vdcs.next();
            infos.add(CmdbInfoConvertor.getInfo(vdc, "delete", null, CloudProvider.VMWARE));
            vdcRepository.remove(vdc.getId(), operator);
        }
    }

    /**
     * 同步集群(更新新增)
     *
     * @param oldClusters
     * @param newClusters
     * @param vendorId
     * @param vdcId
     * @param operator
     * @param storeMap
     * @param oldHostMap
     * @param networkMap
     * @param groupMap
     * @param type
     * @param infos
     * @param vendorGuid
     * @param vdcGuid
     * @param oldServerMap
     * @throws Exception
     */
    private void syncCluster(List<Cluster> oldClusters, List<Cluster> newClusters, Long vendorId, Long vdcId,
                             Long operator, Map<String, DataStore> storeMap, Map<String, Server> oldHostMap,
                             Map<String, Network> networkMap, Map<String, String> groupMap, String type, List<CmdbInfo> infos,
                             String vendorGuid, String vdcGuid, Map<String, CloudServer> oldServerMap, Map<String, Long> dvswitchNameMap)
            throws Exception {
        if (!ListTool.isEmpty(oldClusters) && ListTool.isEmpty(newClusters)) {
            List<Cluster> clusters = clusterRepository.listByVendor(vendorId);
            for (Cluster cluster : clusters) {
                // cmdb：删除集群
                infos.add(CmdbInfoConvertor.getInfo(cluster, "delete", null, CloudProvider.VMWARE));
            }
            clusterRepository.removeByVdc(vdcId, operator);
        } else {
            Map<String, Cluster> oldMap = Maps.newHashMap();
            for (Cluster cluster : oldClusters) {
                if (oldMap.containsKey(cluster.getClusterVal() + cluster.getName())) {
                    clusterRepository.remove(cluster.getId(), operator);
                } else {
                    oldMap.put(cluster.getClusterVal() + cluster.getName(), cluster);
                }
            }
            for (Cluster cluster : newClusters) {
                List<CmdbRelation> relations = Lists.newArrayList();
                relations.add(new CmdbRelation(ModuleCode.VC_DC.name(), 1L, ListUtils.getList(vdcGuid)));
                Long clusterId = null;
                String clusterGuid = null;
                if (oldMap.containsKey(cluster.getClusterVal() + cluster.getName())) {
                    Cluster oldCluster = oldMap.get(cluster.getClusterVal() + cluster.getName());
                    // 更新集群
                    utils.mergeCluster(oldCluster, cluster, operator);
                    clusterId = oldCluster.getId();
                    clusterGuid = oldCluster.getGuid();
                    // 移除存在更新的集群
                    oldMap.remove(cluster.getClusterVal() + cluster.getName());
                    // CMDB更新集群数据
                    infos.add(CmdbInfoConvertor.getInfo(oldCluster, null, relations, CloudProvider.VMWARE));
                } else {
                    cluster.preSave(operator, operator, vendorId, vdcId);
                    cluster.setType(CloudProvider.VMWARE.name());
                    cluster.setUuid(IDFactory.instance().uuid());
                    cluster.setCpuDistributableRatio(BigDecimal.valueOf(100));
                    cluster.setMemDistributableRatio(BigDecimal.valueOf(100));
                    cluster.setCpuExcessRatio(4L);
                    cluster.setStatus("RUNNING");
                    cluster.setCategory("COMPUTE");
                    clusterRepository.save(cluster);
                    clusterId = cluster.getId();
                    clusterGuid = cluster.getGuid();
                    // CMDB添加集群数据
                    infos.add(CmdbInfoConvertor.getInfo(cluster, null, relations, CloudProvider.VMWARE));
                }

                // 同步宿主机
                List<HostSystem> newHostSystems = cluster.getHosts();
                if (null != newHostSystems) {
                    log.info("Start sync host of cluster[" + clusterId + "]");
                    syncHost(storeMap, newHostSystems, oldHostMap, vendorId, vdcId, clusterId, operator, networkMap,
                            groupMap, type, infos, vendorGuid, vdcGuid, clusterGuid, oldServerMap, dvswitchNameMap);
                }
            }
            // 删除不存在的集群
            Iterator<Cluster> clusters = oldMap.values().iterator();
            while (clusters.hasNext()) {
                Cluster cluster = clusters.next();
                infos.add(CmdbInfoConvertor.getInfo(cluster, "delete", null, CloudProvider.VMWARE));
                clusterRepository.remove(cluster.getId(), operator);
            }
        }
    }

    /**
     * 同步网络
     *
     * @param oldNetworks
     * @param newNetworks
     * @param vendorId
     * @param vdcId
     * @param operator
     * @throws Exception
     */
    public void syncNetwork(List<Network> oldNetworks, List<Network> newNetworks, Long vendorId, Long vdcId,
                            Long operator, Map<String, Network> networkMap, Map<String, Long> dvswitchMap, List<CmdbInfo> infos,
                            String vendorGuid, String vdcGuid) throws Exception {
        if (!ListTool.isEmpty(newNetworks)) {// 数据库存在，该数据中心下存在网络，则全部新增更新或删除
            Map<String, Network> oldMap = Maps.newHashMap();
            for (Network network : oldNetworks) {
                oldMap.put(network.getNetworkVal(), network);
            }
            // 不存在此网络则新增，否则更新
            for (Network network : newNetworks) {
                List<CmdbRelation> relations = Lists.newArrayList();
                // relations.add(new CmdbRelation(ModuleCode.VC_VENDOR.name(), 1L,
                // ListUtils.getList(vendorGuid)));
                relations.add(new CmdbRelation(ModuleCode.VC_DC.name(), 1L, ListUtils.getList(vdcGuid)));
                // relations.add(new CmdbRelation(ModuleCode.VC_DC.name(), 2L,
                // ListUtils.getList(vdcGuid)));
                if (oldMap.containsKey(network.getNetworkVal())) {
                    Network oldNetwork = oldMap.get(network.getNetworkVal());
                    oldNetwork.setName(network.getName());
                    oldNetwork.setStatus(network.getStatus());
                    oldNetwork.setPortNum(network.getPortNum());
                    oldNetwork.setSwitcherId(dvswitchMap.get(network.getNetworkVal()));
                    oldNetwork.setMenderId(operator);
                    oldNetwork.setOpaqueNetworkType(network.getOpaqueNetworkType());
                    networkRepository.update(oldNetwork);
                    networkMap.put(oldNetwork.getNetworkVal(), oldNetwork);
                    // 移除存在更新的网络
                    oldMap.remove(network.getNetworkVal());
                    // CMDB更新集群数据
                    if (null != infos) {
                        infos.add(CmdbInfoConvertor.getInfo(oldNetwork, null, relations, CloudProvider.VMWARE));
                    }
                } else {
                    network.preSave(operator, operator, vendorId, vdcId);
                    network.setSwitcherId(dvswitchMap.get(network.getNetworkVal()));
                    networkRepository.save(network);
                    networkMap.put(network.getNetworkVal(), network);
                    // CMDB添加集群数据
                    if (null != infos) {
                        infos.add(CmdbInfoConvertor.getInfo(network, null, relations, CloudProvider.VMWARE));
                    }
                }
            }
            // 删除不存在的网络
            Iterator<Network> networks = oldMap.values().iterator();
            while (networks.hasNext()) {
                networkRepository.remove(networks.next().getId(), operator);
            }
        } else {// 数据库存在，该数据中心不存在网络，则全部删除
            for (Network network : oldNetworks) {
                networkHostRepository.deleteByNetwork(network.getId());
                // cmdb：删除网络
                if (null != infos) {
                    infos.add(CmdbInfoConvertor.getInfo(network, "delete", null, CloudProvider.VMWARE));
                }
            }
            networkRepository.removeByVdc(vdcId, operator);
        }
    }

    /**
     * 同步数据存储
     *
     * @param storeMap
     * @param oldStores
     * @param newStores
     * @param vendorId
     * @param vdcId
     * @param operator
     * @param infos
     * @param vendorGuid
     * @param vdcGuid
     * @throws Exception
     */
    private void syncStore(Map<String, DataStore> storeMap, List<DataStore> oldStores, List<DataStore> newStores,
                           Long vendorId, Long vdcId, Long operator, List<CmdbInfo> infos, String vendorGuid, String vdcGuid)
            throws Exception {
        if (ListTool.isEmpty(oldStores) && !ListTool.isEmpty(newStores)) {// 数据库不存在，该云主机下存在快照，则全部新增
            // 新增
            for (DataStore dataStore : newStores) {
                List<CmdbRelation> relations = Lists.newArrayList();
                // relations.add(new CmdbRelation(ModuleCode.VC_VENDOR.name(), 1L,
                // ListUtils.getList(vendorGuid)));
                relations.add(new CmdbRelation(ModuleCode.VC_DC.name(), 1L, ListUtils.getList(vdcGuid)));
                // relations.add(new CmdbRelation(ModuleCode.VC_DC.name(), 2L,
                // ListUtils.getList(vdcGuid)));
                dataStore.preSave(operator, operator, vendorId, vdcId);
                dataStore.setDistributableRatio(BigDecimal.valueOf(100));
                dataStoreRepository.save(dataStore);
                // 同步数据存储下镜像
                /*
                 * List<Image> oldImages = imageRepository.listByStoreId(dataStore.getId());
                 * syncImage(oldImages, dataStore.getImages(), dataStore.getId(), vendorId,
                 * operator);
                 */
                storeMap.put(dataStore.getStoreVal(), dataStore);
                // cmdb添加数据存储数据
                infos.add(CmdbInfoConvertor.getInfo(dataStore, null, relations, CloudProvider.VMWARE));
            }
        } else if (!ListTool.isEmpty(oldStores) && !ListTool.isEmpty(newStores)) {// 数据库存在，该云主机下存在快照，则全部新增更新或删除
            Map<String, DataStore> oldStore = Maps.newHashMap();
            for (DataStore store : oldStores) {
                oldStore.put(store.getStoreVal(), store);
            }
            // 同步数据存储更新新增
            for (DataStore dataStore : newStores) {
                List<CmdbRelation> relations = Lists.newArrayList();
                // relations.add(new CmdbRelation(ModuleCode.VC_VENDOR.name(), 1L,
                // ListUtils.getList(vendorGuid)));
                relations.add(new CmdbRelation(ModuleCode.VC_DC.name(), 1L, ListUtils.getList(vdcGuid)));
                relations.add(new CmdbRelation(ModuleCode.VC_DC.name(), 2L, ListUtils.getList(vdcGuid)));
                if (oldStore.containsKey(dataStore.getStoreVal())) {
                    DataStore store = oldStore.get(dataStore.getStoreVal());
                    store.setName(dataStore.getName());
                    store.setCapacity(dataStore.getCapacity());
                    store.setFreeSpace(dataStore.getFreeSpace());
                    store.setVdcId(vdcId);
                    store.setMenderId(operator);
                    store.setHostNum(dataStore.getHostNum());
                    store.setVmNum(dataStore.getVmNum());
                    store.setTemplateNum(dataStore.getTemplateNum());
                    store.setStatus(dataStore.getStatus());
                    BigDecimal distributableRatio = store.getDistributableRatio();
                    if (null == distributableRatio) {
                        store.setDistributableRatio(BigDecimal.valueOf(100));
                    }
                    dataStoreRepository.update(store);
                    /*
                     * List<Image> oldImages = imageRepository.listByStoreId(store.getId()); //
                     * 同步数据存储下镜像 syncImage(oldImages, dataStore.getImages(), store.getId(),
                     * vendorId, operator);
                     */
                    storeMap.put(store.getStoreVal(), store);
                    // 移除存在更新的数据存储
                    oldStore.remove(dataStore.getStoreVal());
                    // CMDB添加数据存储数据
                    infos.add(CmdbInfoConvertor.getInfo(store, null, relations, CloudProvider.VMWARE));
                } else {
                    dataStore.preSave(operator, operator, vendorId, vdcId);
                    dataStore.setDistributableRatio(BigDecimal.valueOf(100));
                    dataStoreRepository.save(dataStore);
                    /*
                     * List<Image> oldImages = imageRepository.listByStoreId(dataStore.getId()); //
                     * 同步数据存储下镜像 syncImage(oldImages, dataStore.getImages(), dataStore.getId(),
                     * vendorId, operator);
                     */
                    storeMap.put(dataStore.getStoreVal(), dataStore);
                    // CMDB更新数据存储数据
                    infos.add(CmdbInfoConvertor.getInfo(dataStore, null, relations, CloudProvider.VMWARE));
                }
            }
            // 同步数据存储删除不存在于平台上的数据
            Iterator<DataStore> stores = oldStore.values().iterator();
            while (stores.hasNext()) {
                DataStore store = stores.next();
                // cmdb删除数据存储数据
                infos.add(CmdbInfoConvertor.getInfo(store, "delete", null, CloudProvider.VMWARE));
                // 删除数据存储下镜像
                imageRepository.removeByStoreId(store.getId(), operator);
                // 删除数据存储与主机关机
                storeHostRepository.deleteByStore(store.getId());
                // 删除存储与cmp资源池的关系
                poolGroupRelationRepository.removeByTarget(store.getId(), "Storage");
                dataStoreRepository.remove(store.getId(), operator);
            }
        } else if (!ListTool.isEmpty(oldStores) && ListTool.isEmpty(newStores)) {// 数据库存在，该云主机不存在快照，则全部删除
            for (DataStore store : oldStores) {
                // cmdb删除数据存储数据
                infos.add(CmdbInfoConvertor.getInfo(store, "delete", null, CloudProvider.VMWARE));
                // 删除数据存储下镜像
                imageRepository.removeByStoreId(store.getId(), operator);
                // 删除存储与cmp资源池的关系
                poolGroupRelationRepository.removeByTarget(store.getId(), "Storage");
                storeHostRepository.deleteByStore(store.getId());
            }
            dataStoreRepository.removeByVdc(vdcId, operator);
        }
    }

    /**
     * 同步数据存储下镜像
     *
     * @param oldImages
     * @param newImages
     * @param storeId
     * @param vendorId
     * @param operator
     * @throws Exception
     */
    private void syncImage(List<Image> oldImages, List<Image> newImages, Long storeId, Long vendorId, Long operator)
            throws Exception {
        // 存储下没有任何镜像
        if (!ListTool.isEmpty(oldImages) && ListTool.isEmpty(newImages)) {
            imageRepository.removeByStoreId(storeId, operator);
        } else if (!ListTool.isEmpty(oldImages) && !ListTool.isEmpty(newImages)) {
            Map<String, Image> oldMap = Maps.newHashMap();
            for (Image image : oldImages) {
                oldMap.put(image.getFilePath(), image);
            }
            for (Image image : newImages) {
                if (oldMap.containsKey(image.getFilePath())) {
                    Image oldImage = oldMap.get(image.getFilePath());
                    oldImage.setName(image.getName());
                    oldImage.setFilePath(image.getFilePath());
                    oldImage.setVendorId(vendorId);
                    oldImage.setStoreId(storeId);
                    oldImage.setOsType(image.getOsType());
                    oldImage.setSize(image.getSize());
                    imageRepository.update(oldImage);
                    oldMap.remove(image.getFilePath());
                } else {
                    image.preSave(operator, operator, vendorId, 0L, 0L);
                    image.setStoreId(storeId);
                    image.setVendorType(CloudProvider.VMWARE.name());
                    image.setCatalog("VM");
                    imageRepository.save(image);
                    oldMap.remove(image.getFilePath());
                }
            }
            Iterator<Image> images = oldMap.values().iterator();
            while (images.hasNext()) {
                Long id = images.next().getId();
                imageRepository.remove(id, operator);
            }
        } else if (ListTool.isEmpty(oldImages) && !ListTool.isEmpty(newImages)) {
            for (Image image : newImages) {
                image.setCreatorId(operator);
                image.setVendorId(vendorId);
                image.setStoreId(storeId);
                image.setVendorType(CloudProvider.VMWARE.name());
                image.setCatalog("VM");
                imageRepository.save(image);
            }
        }
    }

    /**
     * 处理ip地址
     *
     * @param vendorId
     * @param address
     * @param catalog
     * @param target
     * @param ipPools
     */
    private void processIp(Long vendorId, String address, String catalog, Long target, List<IpPool> ipPools) {
        Ip ip = ipRepository.checkExist(address, null, vendorId);
        if (null == ip) {
            ip = new Ip(address, null, null, null, vendorId, IDFactory.instance().uuid(), null, IpStatus.used);
            ip.setCatalog(catalog);
            ip.setTarget(target);
            ipRepository.save(ip);
        } else {
            ip.setTarget(target);
            ip.setCatalog(catalog);
            ip.setStatus(IpStatus.used);
            ipRepository.update(ip);
        }
    }

    /**
     * 同步宿主机(新增或更新已存在的宿主机)
     *
     * @param storeMap
     * @param hosts
     * @param oldHostMap
     * @param vendorId
     * @param vdcId
     * @param clusterId
     * @param operator
     * @param networkMap
     * @param groupMap
     * @param type
     * @param infos
     * @param vendorGuid
     * @param vdcGuid
     * @param clusterGuid
     * @param oldServerMap
     * @throws Exception
     */
    private void syncHost(Map<String, DataStore> storeMap, List<HostSystem> hosts, Map<String, Server> oldHostMap,
                          Long vendorId, Long vdcId, Long clusterId, Long operator, Map<String, Network> networkMap,
                          Map<String, String> groupMap, String type, List<CmdbInfo> infos, String vendorGuid, String vdcGuid,
                          String clusterGuid, Map<String, CloudServer> oldServerMap, Map<String, Long> dvswitchNameMap) throws Exception {
        List<IpPool> ipPools = ipPoolRepository.listByIpVersion(null);
        for (HostSystem host : hosts) {
            // 宿主机与对象的关系
            List<CmdbRelation> relations = Lists.newArrayList();
            if (StringUtils.isEmpty(clusterGuid)) {
                relations.add(new CmdbRelation(ModuleCode.VC_DC.name(), 1L, ListUtils.getList(vdcGuid)));
            } else {
                relations.add(new CmdbRelation(ModuleCode.VC_CLUSTER.name(), 1L, ListUtils.getList(clusterGuid)));
            }
            relations.add(new CmdbRelation(ModuleCode.VC_DC.name(), 2L, ListUtils.getList(vdcGuid)));
            // cmdb:宿主机与数据存储关系
            List<String> guids = Lists.newArrayList();
            for (String store : host.getStores()) {
                if (storeMap.containsKey(store)) {
                    guids.add(storeMap.get(store).getGuid());
                }
            }
            relations.add(new CmdbRelation(ModuleCode.VC_DS.name(), 1L, guids));
            // cmdb:宿主机与网络关系
            List<String> networkGuids = Lists.newArrayList();
            Map<String, Network> netMap = Maps.newHashMap();
            for (String key : networkMap.keySet()) {
                netMap.put(key, networkMap.get(key));
            }
            if (!ListTool.isEmpty(host.getNetworks())) {
                List<Network> networks =
                        JSONArray.parseArray(JSONObject.toJSONString(host.getNetworks()), Network.class);
                for (Network network : networks) {
                    String val = network.getNetworkVal();
                    if (netMap.containsKey(val)) {// 网络存在则直接保存,标准网络
                        networkGuids.add(netMap.get(val).getGuid());
                    } else if (groupMap.containsKey(val) && netMap.containsKey(groupMap.get(val))) {// 网络不存，且在端口组中，则是分布式网络
                        networkGuids.add(netMap.get(groupMap.get(val)).getGuid());
                        netMap.remove(groupMap.get(val));
                    }
                }
            }
            relations.add(new CmdbRelation(ModuleCode.VC_NETWORK.name(), 2L, networkGuids));
            Long hostId = null;
            // 更新宿主机以及相关实体对象
            if (oldHostMap.containsKey(host.getUuid() + host.getHostIp())) {
                Server server = oldHostMap.get(host.getUuid() + host.getHostIp());
                hostId = server.getId();
                // 同步主机标准交换机
                List<Switcher> switchers = switcherRepository.listByHostId(hostId);
                syncSwitcher(switchers,
                        JSONArray.parseArray(JSONObject.toJSONString(host.getSwitchers()), Switcher.class), vendorId, vdcId,
                        hostId, operator, "VSWITCH", infos, vendorGuid);
                switchers = switcherRepository.listByHostId(hostId);
                Map<String, Long> switcherMap = Maps.newHashMap();
                for (Switcher switcher : switchers) {
                    switcherMap.put(switcher.getName(), switcher.getId());
                }
                // 更新宿主机
                utils.mergeHost(server, host, vendorId, vdcId, clusterId, operator, storeMap, networkMap, groupMap,
                        switcherMap, ipPools, dvswitchNameMap);
                // 同步该宿主机下的云主机
                List<CloudServer> cloudServers =
                        JSONArray.parseArray(JSONObject.toJSONString(host.getServers()), CloudServer.class);
                log.info("Start sync virtual machine of host[" + server.getId() + "]");
                syncServer(storeMap, oldServerMap, cloudServers, vendorId, server.getId(), vdcId, operator,
                        server.getPowerState(), networkMap, groupMap, type, infos, vendorGuid, server.getGuid());
                // 移除存在更新的宿主机
                oldHostMap.remove(host.getUuid() + host.getHostIp());
                // 同步集群节点
                ClusterNode node = clusterNodeRepository.queryByRid(server.getResourceId());
                if (null != node) {
                    if (null == clusterId) {
                        clusterNodeRepository.removeByRid(node.getResourceId(), operator);
                    } else {
                        node.setClusterId(clusterId);
                        node.setMenderId(operator);
                        node.setIp(server.getManageIp());
                        node.setStatus(server.getStatus());
                        clusterNodeRepository.update(node);
                    }
                }
                ServerConfig config = serverConfigRepository.getBySid(server.getId());
                // cmdb更新宿主机数据
                infos.add(CmdbInfoConvertor.getInfo(server, config, null, relations, CloudProvider.VMWARE));
                syncScsiLun(host.getScsiLunModels(), vendorId, hostId);
                // 宿主机和存储建立关系
                // 先删除，再添加
                storeHostRepository.deleteByHost(hostId, "PM");
                utils.addStore(vendorId, hostId, operator, "PM", host.getStores(), storeMap);
            } else {
                // 判断ipmi IP是否已存在
                ServerConfig config = serverConfigRepository.getConfig(host.getIpmiAddress());
                Server server = null;
                if (null != config) {
                    config.setDiskCapacity(host.getDiskTotal());
                    config.setCpuHz(host.getCpuTotal());
                    config.setMemoryCapacity(host.getMemTotal());
                    config.setCpuAmount(host.getCpuNum());
                    config.setCpuMode(host.getCpuModel());
                    config.setCpuCore(host.getCpuCore());
                    config.setCpuUsed(host.getCpuUsed());
                    config.setMemUsed(host.getMemUsed());
                    config.setDiskUsed(host.getDiskUsed());
                    config.setVendor(host.getVendor());
                    config.setEsxVersion(host.getEsxVersion());
                    config.setEvc(host.getEvc());
                    config.setAssignedLicense(host.getAssignedLicense());
                    config.setIpmiAddress(host.getIpmiAddress());
                    config.setIpmiAccount(host.getIpmiAccount());
                    config.setIpmiPassword(host.getIpmiPassword());
                    config.setIpmiPort(623);
                    server = serverRepository.query(config.getServerId());
                    if (null == server) {
                        server = new Server();
                        BeanUtils.copyProperties(host, server);
                        server.setManageIp(host.getHostIp());
                        server.setResourceId(IDFactory.instance().uuid());
                        server.preSave(operator, operator, vendorId, vdcId, clusterId);
                        server.setOsCategory("ESXi");
                        server.setAssetCategory(ServerAssetCategory.HYPERVISOR.name());
                        serverRepository.save(server);
                        this.processIp(server.getVendorId(), server.getManageIp(), "PM", hostId, ipPools);
                        // 保存资源
                        List<String> privateIps = Lists.newArrayList();
                        privateIps.add(server.getManageIp());
                        Resource resource =
                                new Resource(ResourceCategory.Computer.name(), ResourceCatalog.PHYSICAL.name(),
                                        server.getId(), JSONObject.toJSONString(privateIps), server.getCatalog(), vendorId);
                        resource.preSave(server.getName(), server.getStatus(), operator, 0L);
                        resource.setInventory(JSONObject.toJSONString(server));
                        resourceRepository.save(resource);
                    } else {
                        BeanUtils.copyProperties(host, server);
                        server.setManageIp(host.getHostIp());
                        server.setVdcId(vdcId);
                        server.setClusterId(clusterId);
                        server.setVendorId(vendorId);
                        server.setMenderId(operator);
                        server.setAssetCategory(ServerAssetCategory.HYPERVISOR.name());
                        serverRepository.update(server);
                        // 更新资源
                        Resource resource = resourceRepository.query(ResourceCategory.Computer.name(),
                                ResourceCatalog.PHYSICAL.name(), server.getId());
                        List<String> privateIps = Lists.newArrayList();
                        privateIps.add(server.getManageIp());
                        if (null == resource) {
                            resource = new Resource(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
                                    server.getId(), JSONObject.toJSONString(privateIps), OSCategory.LINUX.name(), vendorId);
                            resource.preSave(server.getName(), server.getPowerState(), operator, 0L);
                            resource.setInventory(JSONObject.toJSONString(server));
                            resourceRepository.save(resource);
                        } else {
                            resource.setStatus(server.getPowerState());
                            resource.setPrivateIps(JSONObject.toJSONString(privateIps));
                            resource.setMenderId(operator);
                            resourceRepository.update(resource);
                        }
                    }
                    hostId = server.getId();
                    config.setServerId(hostId);
                    serverConfigRepository.update(config);
                    server.setConfig(config);
                } else {
                    server = new Server();
                    BeanUtils.copyProperties(host, server);
                    server.setManageIp(host.getHostIp());
                    server.setResourceId(IDFactory.instance().uuid());
                    server.preSave(operator, operator, vendorId, vdcId, clusterId);
                    server.setOsCategory("ESXi");
                    server.setAssetCategory(ServerAssetCategory.HYPERVISOR.name());
                    serverRepository.save(server);
                    hostId = server.getId();
                    // 保存主机配置信息
                    config = utils.addServerConfig(host, hostId);
                    server.setConfig(config);
                    this.processIp(server.getVendorId(), server.getManageIp(), "PM", hostId, ipPools);
                    // 保存资源
                    List<String> privateIps = Lists.newArrayList();
                    privateIps.add(server.getManageIp());
                    Resource resource = new Resource(ResourceCategory.Computer.name(), ResourceCatalog.PHYSICAL.name(),
                            server.getId(), JSONObject.toJSONString(privateIps), server.getCatalog(), vendorId);
                    resource.preSave(server.getName(), server.getStatus(), operator, 0L);
                    resource.setInventory(JSONObject.toJSONString(server));
                    resourceRepository.save(resource);
                    syncScsiLun(host.getScsiLunModels(), vendorId, hostId);
                }
                // 保存标准交换机
                Map<String, Long> switcherMap = Maps.newHashMap();
                for (Switcher switcher : JSONArray.parseArray(JSONObject.toJSONString(host.getSwitchers()),
                        Switcher.class)) {
                    switcher.preSave(operator, operator, vendorId, server.getVdcId(), hostId);
                    switcherRepository.save(switcher);
                    for (PortGroup group : switcher.getGroups()) {
                        group.preSave(operator, operator, vendorId, switcher.getId());
                        portGroupRepository.save(group);
                    }
                    switcherMap.put(switcher.getName(), switcher.getId());
                }
                // 保存物理网卡
                utils.addCard(vendorId, hostId, operator, "PM",
                        JSONArray.parseArray(JSONObject.toJSONString(host.getNetcards()), NetworkCard.class), switcherMap,
                        dvswitchNameMap);
                // 保存云主机
                List<CloudServer> cloudServers =
                        JSONArray.parseArray(JSONObject.toJSONString(host.getServers()), CloudServer.class);
                syncServer(storeMap, oldServerMap, cloudServers, vendorId, server.getId(), vdcId, operator,
                        server.getPowerState(), networkMap, groupMap, type, infos, vendorGuid, server.getGuid());
                // 宿主机和存储建立关系
                utils.addStore(vendorId, hostId, operator, "PM", host.getStores(), storeMap);
                // 宿主机和网络建立关系
                utils.addNetwork(vendorId, hostId, operator, "PM",
                        JSONArray.parseArray(JSONObject.toJSONString(host.getNetworks()), Network.class), networkMap,
                        groupMap);
                // 同步到集群节点
                if (null != clusterId) {
                    ClusterNode node = new ClusterNode(server.getManageIp(), server.getResourceId(), "PM", clusterId);
                    node.setName(host.getName());
                    node.setCreatorId(operator);
                    node.setMenderId(operator);
                    node.setStatus(host.getStatus());
                    clusterNodeRepository.save(node);
                }
                // cmdb添加宿主机数据
                infos.add(CmdbInfoConvertor.getInfo(server, config, null, relations, CloudProvider.VMWARE));
            }
        }
    }

    /**
     * 删除不存在的宿主机
     *
     * @param oldHostMap
     * @param operator
     * @param infos
     * @throws Exception
     */
    private void removeHost(Map<String, Server> oldHostMap, Long operator, List<CmdbInfo> infos) throws Exception {
        Iterator<Server> hosts = oldHostMap.values().iterator();
        while (hosts.hasNext()) {
            Server host = hosts.next();
            Long hostId = host.getId();
            storeHostRepository.deleteByHost(hostId, "PM");
            networkHostRepository.deleteByHost(hostId, "PM");
            networkCardRepository.removeByHost(hostId, "PM", operator);
            List<Switcher> switchers = switcherRepository.listByHostId(hostId);
            for (Switcher switcher : switchers) {
                portGroupRepository.removeBySwitcher(switcher.getId(), operator);
            }
            switcherRepository.removeByHostId(hostId, operator);
            List<CloudServer> servers = cloudServerRepository.listByHid(hostId);
            for (CloudServer server : servers) {
                snapshotRepository.removeByVm(server.getId(), operator);
                storeHostRepository.deleteByHost(server.getId(), "VM");
                networkHostRepository.deleteByHost(server.getId(), "VM");
                networkCardRepository.removeByHost(server.getId(), "VM", operator);
                resourceRepository.remove(server.getId(), ResourceCategory.Computer.name(),
                        ResourceCatalog.LOGICAL.name(), operator);
                // 回收IP
                ipRepository.delete(server.getId(), "VM", server.getVendorId());
                // cmdb删除云主机
                infos.add(CmdbInfoConvertor.getInfo(server, "delete", null, CloudProvider.VMWARE));
            }
            // cmdb删除宿主机
            infos.add(CmdbInfoConvertor.getInfo(host, null, "delete", null, CloudProvider.VMWARE));
            cloudServerRepository.removeByHost(hostId, operator);
            serverAssetsRepository.removeBySid(hostId);
            serverConfigRepository.removeBySid(hostId);
            resourceRepository.remove(hostId, ResourceCategory.Computer.name(), ResourceCatalog.PHYSICAL.name(),
                    operator);
            serverRepository.remove(hostId, operator);
            // 回收IP
            ipRepository.delete(host.getId(), "PM", host.getVendorId());
            // 删除集群节点
            clusterNodeRepository.removeByRid(host.getResourceId(), operator);
            scsiLunRepository.removeByHostId(hostId);
        }
    }

    /**
     * 同步云主机下相关数据
     *
     * @param storeMap
     * @param oldServerMap
     * @param newServers
     * @param vendorId
     * @param hostId
     * @param vdcId
     * @param operator
     * @param status
     * @param networkMap
     * @param groupMap
     * @param type
     * @param infos
     * @param vendorGuid
     * @param serverGuid
     * @throws Exception
     */
    private void syncServer(Map<String, DataStore> storeMap, Map<String, CloudServer> oldServerMap,
                            List<CloudServer> newServers, Long vendorId, Long hostId, Long vdcId, Long operator, String status,
                            Map<String, Network> networkMap, Map<String, String> groupMap, String type, List<CmdbInfo> infos,
                            String vendorGuid, String serverGuid) throws Exception {
        if (!ListTool.isEmpty(newServers)) {
            List<IpPool> pools = ipPoolRepository.listByIpVersion(null);
            for (CloudServer cloudServer : newServers) {
                // 云主机与对象的关系
                List<CmdbRelation> relations = Lists.newArrayList();
                relations.add(new CmdbRelation(ModuleCode.VC_PM.name(), 1L, ListUtils.getList(serverGuid)));
                relations.add(new CmdbRelation(ModuleCode.VC_PM.name(), 2L, ListUtils.getList(serverGuid)));
                // cmdb:云主机与数据存储关系
                List<String> storeGuids = Lists.newArrayList();
                if (!ListTool.isEmpty(cloudServer.getStores())) {
                    for (String store : cloudServer.getStores()) {
                        if (storeMap.containsKey(store)) {
                            storeGuids.add(storeMap.get(store).getGuid());
                        }
                    }
                }
                relations.add(new CmdbRelation(ModuleCode.VC_DS.name(), 1L, storeGuids));
                // cmdb:云主机与网络关系
                List<String> networkGuids = Lists.newArrayList();
                Map<String, Network> netMap = Maps.newHashMap();
                for (String key : networkMap.keySet()) {
                    netMap.put(key, networkMap.get(key));
                }
                if (!ListTool.isEmpty(cloudServer.getNetworks())) {
                    for (Network network : cloudServer.getNetworks()) {
                        String val = network.getNetworkVal();
                        if (netMap.containsKey(val)) {// 网络存在则直接保存,标准网络
                            networkGuids.add(netMap.get(val).getGuid());
                        } else if (groupMap.containsKey(val) && netMap.containsKey(groupMap.get(val))) {// 网络不存，且在端口组中，则是分布式网络
                            networkGuids.add(netMap.get(groupMap.get(val)).getGuid());
                            netMap.remove(groupMap.get(val));
                        }
                    }
                }
                relations.add(new CmdbRelation(ModuleCode.VC_NETWORK.name(), 2L, networkGuids));
                if (oldServerMap.containsKey(cloudServer.getInstanceId())
                        || oldServerMap.containsKey(cloudServer.getName())) {
                    CloudServer server = null;
                    if (oldServerMap.containsKey(cloudServer.getInstanceId())) {
                        server = oldServerMap.get(cloudServer.getInstanceId());
                        // 移除存在更新的云主机
                        oldServerMap.remove(cloudServer.getInstanceId());
                    } else {
                        server = oldServerMap.get(cloudServer.getName());
                        // 移除存在更新的云主机
                        oldServerMap.remove(cloudServer.getName());
                    }
                    // 更新云主机
                    utils.mergeServer(server, cloudServer, status, vendorId, hostId, operator, storeMap, networkMap,
                            groupMap, type, pools);
                    // cmdb更新云主机数据
                    infos.add(CmdbInfoConvertor.getInfo(server, null, relations, CloudProvider.VMWARE));
                } else {
                    cloudServer.setVendorType(type);
                    utils.addServerCascade(storeMap, cloudServer, vendorId, hostId, vdcId, operator, status,
                            networkMap, groupMap, type, pools);
                    // cmdb添加云主机数据
                    infos.add(CmdbInfoConvertor.getInfo(cloudServer, null, relations, CloudProvider.VMWARE));
                }
            }
        }
    }

    private void removeServerCascade(CloudServer server, Long operator, Long vendorId) throws Exception {
        String status = server.getStatus();
        Long id = server.getId();
        if (BocloudStatus.Server.BUILDING.name().equals(status)) {
            return;
        }
        if (server.getIsTemplate()) {
            imageRepository.removeByTemplate(id, operator);
        }
        snapshotTaskService.removeByVmId(id);
        snapshotRepository.removeByVm(id, operator);
        storeHostRepository.deleteByHost(id, "VM");
        networkHostRepository.deleteByHost(id, "VM");
        networkCardRepository.removeByHost(id, "VM", operator);
        resourceRepository.remove(id, ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(), operator);
        cloudServerRepository.remove(id, operator);
        // 回收IP
        // ipRepository.delete(server.getId(), "VM", server.getVendorId());
        ipRepository.makeFreeByTarget(server.getId(), "VM", vendorId);
    }

    @SuppressWarnings("unchecked")
    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");
                    }
                    Vdc vdc = vdcRepository.getByValue(datacenter.getMOR().getVal(), vendor.getId());
                    if (null != vdc) {
                        Long vdcId = vdc.getId();
                        // 同步分布式交换机
                        List<Switcher> switchers = switcherRepository.listByVdc(vdcId, "DVSWITCH");
                        log.info("Start sync dvswitcher of datacenter[" + vdcId + "]");
                        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);
                        log.info("Start sync network of datacenter[" + vdcId + "]");
                        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) {
            log.error("Get error message：", e);
            return new BocloudResult<>(false, "网络同步失败");
        }
    }


}
