package com.bocloud.ims.service.transportor;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.common.LocationDriver;
import com.bocloud.cmp.driver.pbm.PbmProfileDriver;
import com.bocloud.cmp.entity.enums.*;
import com.bocloud.cmp.model.DataStoreModel;
import com.bocloud.cmp.model.HostSystem;
import com.bocloud.cmp.model.ImageModel;
import com.bocloud.cmp.model.ScsiLunModel;
import com.bocloud.cmp.model.pbm.PbmProfileModel;
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.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.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.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.topology.InstanceMessageDispatcher;
import com.bocloud.ims.service.utils.CmdbInfoConvertor;
import com.bocloud.ims.service.utils.IPAddress;
import com.bocloud.ims.service.utils.ListUtils;
import com.bocloud.ims.service.utils.SyncVmwareUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
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
 */
public class VmwareTransportor {
    private static Logger logger = LoggerFactory.getLogger(VmwareTransportor.class);
    private VdcRepository vdcRepository;
    private CloudServerRepository cloudServerRepository;
    private DataStoreRepository dataStoreRepository;
    private SnapshotRepository snapshotRepository;
    private NetworkRepository networkRepository;
    private ClusterRepository clusterRepository;
    private StoreHostRepository storeHostRepository;
    private ServerRepository serverRepository;
    private NetworkCardRepository networkCardRepository;
    private PortGroupRepository portGroupRepository;
    private NetworkHostRepository networkHostRepository;
    private SyncVmwareUtils utils;
    private ClusterNodeRepository clusterNodeRepository;
    private ServerConfigRepository serverConfigRepository;
    private ServerAssetsRepository serverAssetsRepository;
    private ResourceRepository resourceRepository;
    private IpRepository ipRepository;
    private IpPoolRepository ipPoolRepository;
    private SwitcherRepository switcherRepository;
    private ImageRepository imageRepository;
    private ResourcePoolRepository resourcePoolRepository;
    private ServerLabelRepository serverLabelRepository;
    private AmqpTemplate amqpTemplate;
    private IpService ipService;
    private LocationDriver locationDriver;
    private PbmProfileDriver profileDriver;
    private PbmProfileRepository profileRepository;
    private ScsiLunRepository scsiLunRepository;
    private IpPoolPortGroupRepository ipPoolPortGroupRepository;
    private VAppRepository vAppRepository;
    private ThreadPoolTaskExecutor taskExecutor;
    private InstanceMessageDispatcher messageDispatcher;
    private SnapshotTaskService snapshotTaskService;

    public VmwareTransportor() {
        super();
    }

    public VmwareTransportor(ResourcePoolRepository resourcePoolRepository, ClusterRepository clusterRepository,
                             ServerRepository serverRepository) {
        super();
        this.clusterRepository = clusterRepository;
        this.serverRepository = serverRepository;
        this.resourcePoolRepository = resourcePoolRepository;
    }

    public VmwareTransportor(VdcRepository vdcRepository, CloudServerRepository cloudServerRepository,
                             DataStoreRepository dataStoreRepository, SnapshotRepository snapshotRepository,
                             NetworkRepository networkRepository, ClusterRepository clusterRepository,
                             StoreHostRepository storeHostRepository, ServerRepository serverRepository,
                             NetworkCardRepository networkCardRepository, PortGroupRepository portGroupRepository,
                             NetworkHostRepository networkHostRepository, ClusterNodeRepository clusterNodeRepository,
                             ServerConfigRepository serverConfigRepository, ServerAssetsRepository serverAssetsRepository,
                             ResourceRepository resourceRepository, IpRepository ipRepository, IpPoolRepository ipPoolRepository,
                             ImageRepository imageRepository, SwitcherRepository switcherRepository,
                             ResourcePoolRepository resourcePoolRepository, VolumeRepository volumeRepository,
                             ServerLabelRepository serverLabelRepository, 
                             AmqpTemplate amqpTemplate, IpService ipService, LocationDriver locationDriver,
                             PbmProfileDriver profileDriver, PbmProfileRepository profileRepository, ScsiLunRepository scsiLunRepository,
                             IpPoolPortGroupRepository ipPoolPortGroupRepository, VAppRepository vAppRepository,
                             ThreadPoolTaskExecutor taskExecutor, InstanceMessageDispatcher messageDispatcher, SnapshotTaskService snapshotTaskService) {
        super();
        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.serverLabelRepository = serverLabelRepository;
        this.amqpTemplate = amqpTemplate;
        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.utils = new SyncVmwareUtils(cloudServerRepository, dataStoreRepository, serverRepository,
                snapshotRepository, networkRepository, clusterRepository, storeHostRepository, networkCardRepository,
                portGroupRepository, networkHostRepository, serverConfigRepository, resourceRepository, ipRepository,
                imageRepository, volumeRepository);
    }

    /**
     * 同步平台实体
     *
     * @param vendor
     * @param data
     * @param managerId
     */
    public BocloudResult sync(CloudVendor vendor, Object data, Long managerId) {
        CmdbModel model = new CmdbModel();
        model.setUuid(IDFactory.instance().uuid());
        model.setServiceName(BoCloudService.IMS.name());
        model.setManagerId(managerId);
        List<CmdbInfo> infos = Lists.newArrayList();
        // 添加云平台数据
        infos.add(CmdbInfoConvertor.getInfo(vendor, null, null, CloudProvider.VMWARE));
        try {
            if (null != data) {
                Long vendorId = vendor.getId();
                if (cloudServerRepository.hasBuilding(vendorId)) {
                    return new BocloudResult(false, "该平台下有虚拟机正在创建，请稍后进行同步操作");
                }
                if (snapshotRepository.hasBuilding(vendorId)) {
                    return new BocloudResult(false, "该平台下有快照正在创建，请稍后进行同步操作");
                }
                // 获取数据库的平台数据
                List<Server> hosts = serverRepository.listByVendor(vendorId);
                Map<String, Server> oldHostMap = Maps.newHashMap();
                for (Server host : hosts) {
                    oldHostMap.put(host.getUuid() + host.getManageIp(), host);
                }
                List<Vdc> vdcs = vdcRepository.listByVendor(vendorId);
                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);
                logger.info("Start sync datacenter of vendor[" + vendorId + "]");
                for (Vdc vdc : allVdcs) {
                    logger.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(managerId);
                        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(managerId, managerId, vendorId);
                        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");
                    logger.info("Start sync dvswitcher of datacenter[" + vdcId + "]");
                    syncSwitcher(switchers, vdc.getSwitchers(), vendorId, vdcId, null, managerId, "DVSWITCH", infos,
                            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> networks = networkRepository.listByVdc(vdcId);
                    Map<String, Network> networkMap = Maps.newHashMap();
                    logger.info("Start sync network of datacenter[" + vdcId + "]");
                    syncNetwork(networks, vdc.getNetworks(), vendorId, vdcId, managerId, networkMap, dvswitchMap, infos,
                            vendor.getGuid(), vdcGuid);
                    // 同步存储
                    Map<String, DataStore> storeMap = new HashMap<>();
                    List<DataStore> stores = dataStoreRepository.listByVdc(vdcId);
                    logger.info("Start sync data store and image of datacenter[" + vdcId + "]");
                    syncStore(storeMap, stores, vdc.getStores(), vendorId, vdcId, managerId, 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, vendorId, managerId);
                                }
                            }
                        } catch (Exception e) {
                            logger.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);
                        }
                    }
                    // 同步宿主机
                    List<HostSystem> newHostSystems = vdc.getHosts();
                    if (!ListTool.isEmpty(newHostSystems)) {
                        logger.info("Start sync host of datacenter[" + vdcId + "]");
                        syncHost(storeMap, newHostSystems, oldHostMap, vendorId, vdcId, null, managerId, networkMap,
                                groupMap, vendor.getType(), infos, vendor.getGuid(), vdcGuid, null, oldServerMap);
                    }
                    // 同步集群
                    List<Cluster> clusters = clusterRepository.listByVdc(vdcId);
                    logger.info("Start sync cluster of datacenter[" + vdcId + "]");
                    syncCluster(clusters, vdc.getClusters(), vendorId, vdcId, managerId, storeMap, oldHostMap,
                            networkMap, groupMap, vendor.getType(), infos, vendor.getGuid(), vdcGuid, oldServerMap);
                    // 删除当前云平台下不存在的虚拟机相关数据
                    Iterator<CloudServer> removeServers = oldServerMap.values().iterator();
                    while (removeServers.hasNext()) {
                        CloudServer removeServer = removeServers.next();
                        removeServerCascade(removeServer, managerId, vendorId);
                        // cmdb删除虚拟机数据
                        infos.add(CmdbInfoConvertor.getInfo(removeServer, "delete", null, CloudProvider.VMWARE));
                    }
                    // 同步资源池
                    List<VmResourcePool> pools = resourcePoolRepository.listByVdc(vdcId);
                    logger.info("Start sync resource pool of datacenter[" + vdcId + "]");
                    syncResourcePool(pools, vdc.getPools(), vdcId, vendorId, managerId);
                    // 同步虚拟机所在资源池信息
                    logger.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);
                                }
                            }
                        }
                    }
                    logger.info("End sync resource pool of datacenter[" + vdcId + "]");
                    // 同步vapp
                    logger.info("Start sync vapp of datacenter[" + vdcId + "]");
                    List<VApp> oldVapps = vAppRepository.listByVdc(vdcId);
                    syncVapp(oldVapps, vdc.getVapps(), vdcId, vendorId, managerId);
                    logger.info("End sync vapp of datacenter[" + vdcId + "]");
                    logger.info("End sync vapp of datacenter[" + vdcId + "]");
                    syncVappVmRelation(finalVdcId, managerId);
                }
                // 同步数据中心，删除不存在的数据中心
                logger.info("Remove data centers that does not exists");
                syncVdc(oldVdcMap, managerId, infos);
                // 同步宿主机，删除不存在的宿主机
                logger.info("Remove hosts that does not exists");
                removeHost(oldHostMap, managerId, infos);
            }
            // 6.0以下不支持vcenter存储策略
            if (!"6.0".equals(vendor.getVersion()) && !"5.5".equals(vendor.getVersion())) {
                // 同步存储策略
                BocloudResult result = profileDriver.list(vendor.getUuid());
                if (result.isSuccess()) {
                    logger.info("Start sync vcenter pbm profile");
                    List<PbmProfileModel> profileModels = JSONArray
                            .parseArray(JSONObject.toJSONString(result.getData()), PbmProfileModel.class);
                    syncPbmProfile(profileModels, vendor.getId());
                    logger.info("End sync vcenter pbm profile");
                }
            }
            // 删除IP表中不存在的脏数据
            ipService.processRubbishIp(vendor.getId());
            model.setData(infos);
            // 发送消息到cmdb模块，进行数据同步
//            amqpTemplate.convertAndSend("cmdb.message.queue", JSONObject.parseObject(JSONObject.toJSONString(model)));
            messageDispatcher.cacheMessage(JSONObject.toJSONString(model));
            return new BocloudResult(true, "云平台【 " + vendor.getName() + " 】数据同步成功");
        } catch (Exception e) {
            logger.error("Sync error:", e);
            return new BocloudResult(false, "云平台【 " + vendor.getName() + " 】数据同步失败:" + e.getMessage());
        }
    }

    private void syncVappVmRelation(Long vdcId, Long managerId) 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()));
        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(managerId);
                    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 managerId
     * @throws Exception
     */
    public void syncVapp(List<VApp> oldVapps, List<VApp> newVapps, Long vdcId, Long vendorId, Long managerId)
            throws Exception {
        if (!ListTool.isEmpty(oldVapps) && ListTool.isEmpty(newVapps)) {
            vAppRepository.removeByVdc(vdcId, managerId);
        } 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(managerId);
                    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(managerId);
                    vAppRepository.save(newVapp);
                }
                oldMap.remove(newVapp.getVappVal());
            }
            Iterator<VApp> vapps = oldMap.values().iterator();
            while (vapps.hasNext()) {
                vAppRepository.remove(vapps.next().getId(), managerId);
            }
            // 处理上下级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(managerId);
                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(managerId);
                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(managerId);
                vAppRepository.update(vapp);
            }
        }
    }

    public void syncResourcePool(List<VmResourcePool> oldPools, List<VmResourcePool> newPools, Long vdcId, Long vendorId,
                                 Long managerId) throws Exception {
        if (!ListTool.isEmpty(oldPools) && ListTool.isEmpty(newPools)) {
            resourcePoolRepository.removeByVdc(vdcId, managerId);
        } 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(managerId);
                    // 资源池所属
                    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(managerId, managerId, vendorId, 0L);
                    resourcePoolRepository.save(newPool);
                    oldMap.remove(newPool.getPoolVal());
                }
            }
            Iterator<VmResourcePool> pools = oldMap.values().iterator();
            while (pools.hasNext()) {
                resourcePoolRepository.remove(pools.next().getId(), managerId);
            }
        } 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(managerId, managerId, vendorId, 0L);
                resourcePoolRepository.save(newPool);
            }
        }
    }

    public void syncSwitcher(List<Switcher> oldSwitchers, List<Switcher> newSwitchers, Long vendorId, Long vdcId,
                             Long hostId, Long managerId, 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(), managerId);
                portGroupRepository.removeBySwitcher(switcher.getId(), managerId);
            }
            if ("DVSWITCH".equals(type)) {
                switcherRepository.removeByVdc(vdcId, "DVSWITCH", managerId);
            } else {
                switcherRepository.removeByHostId(hostId, managerId);
            }
        } 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(managerId);
                    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(managerId, managerId, 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, managerId, 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, managerId);
                portGroupRepository.removeBySwitcher(switcherId, managerId);
                switcherRepository.remove(switcherId, managerId);
            }
        }
    }

    private void syncPortGroup(List<PortGroup> oldGroups, List<PortGroup> newGroups, Long vendorId, Long switcherId,
                               Long managerId, 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, managerId);
        } 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(managerId);
                            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(managerId, managerId, 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(), managerId);
                        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(managerId);
                            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(managerId, managerId, 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(), managerId);
                        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(managerId, managerId, vendorId, switcherId);
                portGroupRepository.save(group);
                infos.add(CmdbInfoConvertor.getInfo(group, null, relations, CloudProvider.VMWARE));
            }
        }
    }

    /**
     * 同步数据中心(删除)
     *
     * @param oldVdcMap
     * @param managerId
     * @param infos
     * @throws Exception
     */
    private void syncVdc(Map<String, Vdc> oldVdcMap, Long managerId, 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(), managerId);
        }
    }

    /**
     * 同步集群(更新新增)
     *
     * @param oldClusters
     * @param newClusters
     * @param vendorId
     * @param vdcId
     * @param managerId
     * @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 managerId, 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) 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, managerId);
        } else {
            Map<String, Cluster> oldMap = Maps.newHashMap();
            for (Cluster cluster : oldClusters) {
                if (oldMap.containsKey(cluster.getClusterVal() + cluster.getName())) {
                    clusterRepository.remove(cluster.getId(), managerId);
                } 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, managerId);
                    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(managerId, managerId, 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) {
                    logger.info("Start sync host of cluster[" + clusterId + "]");
                    syncHost(storeMap, newHostSystems, oldHostMap, vendorId, vdcId, clusterId, managerId, networkMap,
                            groupMap, type, infos, vendorGuid, vdcGuid, clusterGuid, oldServerMap);
                }
            }
            // 删除不存在的集群
            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(), managerId);
            }
        }
    }

    /**
     * 同步网络
     *
     * @param oldNetworks
     * @param newNetworks
     * @param vendorId
     * @param vdcId
     * @param managerId
     * @throws Exception
     */
    public void syncNetwork(List<Network> oldNetworks, List<Network> newNetworks, Long vendorId, Long vdcId,
                            Long managerId, 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(managerId);
                    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(managerId, managerId, 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(), managerId);
            }
        } 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, managerId);
        }
    }

    /**
     * 同步数据存储
     *
     * @param storeMap
     * @param oldStores
     * @param newStores
     * @param vendorId
     * @param vdcId
     * @param managerId
     * @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 managerId, 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(managerId, managerId, vendorId, vdcId);
                dataStore.setDistributableRatio(BigDecimal.valueOf(100));
                dataStoreRepository.save(dataStore);
                // 同步数据存储下镜像
                /*
                 * List<Image> oldImages = imageRepository.listByStoreId(dataStore.getId());
                 * syncImage(oldImages, dataStore.getImages(), dataStore.getId(), vendorId,
                 * managerId);
                 */
                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(managerId);
                    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, managerId);
                     */
                    storeMap.put(store.getStoreVal(), store);
                    // 移除存在更新的数据存储
                    oldStore.remove(dataStore.getStoreVal());
                    // CMDB添加数据存储数据
                    infos.add(CmdbInfoConvertor.getInfo(store, null, relations, CloudProvider.VMWARE));
                } else {
                    dataStore.preSave(managerId, managerId, vendorId, vdcId);
                    dataStore.setDistributableRatio(BigDecimal.valueOf(100));
                    dataStoreRepository.save(dataStore);
                    /*
                     * List<Image> oldImages = imageRepository.listByStoreId(dataStore.getId()); //
                     * 同步数据存储下镜像 syncImage(oldImages, dataStore.getImages(), dataStore.getId(),
                     * vendorId, managerId);
                     */
                    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(), managerId);
                // 删除数据存储与主机关机
                storeHostRepository.deleteByStore(store.getId());
                dataStoreRepository.remove(store.getId(), managerId);
            }
        } 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(), managerId);
                storeHostRepository.deleteByStore(store.getId());
            }
            dataStoreRepository.removeByVdc(vdcId, managerId);
        }
    }

    /**
     * 同步数据存储下镜像
     *
     * @param oldImages
     * @param newImages
     * @param storeId
     * @param vendorId
     * @param managerId
     * @throws Exception
     */
    private void syncImage(List<Image> oldImages, List<Image> newImages, Long storeId, Long vendorId, Long managerId)
            throws Exception {
        // 存储下没有任何镜像
        if (!ListTool.isEmpty(oldImages) && ListTool.isEmpty(newImages)) {
            imageRepository.removeByStoreId(storeId, managerId);
        } 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(managerId, managerId, 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, managerId);
            }
        } else if (ListTool.isEmpty(oldImages) && !ListTool.isEmpty(newImages)) {
            for (Image image : newImages) {
                image.setCreatorId(managerId);
                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);
            for (IpPool pool : ipPools) {
                String dns = null;
                if (!StringUtils.isEmpty(pool.getDnsNames())) {
                    List<String> dnss = JSONArray.parseArray(pool.getDnsNames(), String.class);
                    if (!ListTool.isEmpty(dnss)) {
                        dns = dnss.get(0);
                    }
                }
                List<String> poolList = JSONArray.parseArray(pool.getPools(), String.class);
                IPAddress ipAddress = IPAddress.getIPAddress(address);
                boolean flag = ipAddress.isInPools(address, poolList);
                if (flag) {
                    ip.setMask(ipAddress.getMask(pool.getCidr()));
                    ip.setGateway(pool.getGateway());
                    ip.setDns(dns);
                    ip.setPoolId(pool.getId());
                    break;
                }
            }
            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 managerId
     * @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 managerId, Map<String, Network> networkMap,
                          Map<String, String> groupMap, String type, List<CmdbInfo> infos, String vendorGuid, String vdcGuid,
                          String clusterGuid, Map<String, CloudServer> oldServerMap) 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, managerId, "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, managerId, storeMap, networkMap, groupMap,
                        switcherMap, ipPools);
                // 同步该宿主机下的虚拟机
                List<CloudServer> cloudServers = JSONArray.parseArray(JSONObject.toJSONString(host.getServers()), CloudServer.class);
                logger.info("Start sync virtual machine of host[" + server.getId() + "]");
                syncServer(storeMap, oldServerMap, cloudServers, vendorId, server.getId(), vdcId, managerId,
                        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(), managerId);
                    } else {
                        node.setClusterId(clusterId);
                        node.setMenderId(managerId);
                        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);
            } 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(managerId, managerId, vendorId, vdcId, clusterId);
                        server.setOsCategory("ESXi");
                        server.setAssetCategory(ServerAssetCategory.HYPERVISOR.name());
                        serverRepository.save(server);
                        // 处理IP地址
//						if (!StringUtils.isEmpty(server.getManageIp())) {
//							Ip ip = new Ip(server.getManageIp(), null, null, null, vendorId,
//									IDFactory.instance().uuid(), null);
//							ip.setCatalog("PM");
//							ip.setTarget(hostId);
//							ipRepository.save(ip);
//						}
                        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(), managerId, 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(managerId);
                        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(), managerId, 0L);
                            resource.setInventory(JSONObject.toJSONString(server));
                            resourceRepository.save(resource);
                        } else {
                            resource.setStatus(server.getPowerState());
                            resource.setPrivateIps(JSONObject.toJSONString(privateIps));
                            resource.setMenderId(managerId);
                            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(managerId, managerId, 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);
                    // 处理IP地址
//					if (!StringUtils.isEmpty(server.getManageIp())) {
//						Ip ip = new Ip(server.getManageIp(), null, null, null, vendorId, IDFactory.instance().uuid(),
//								null);
//						ip.setCatalog("PM");
//						ip.setTarget(hostId);
//						ipRepository.save(ip);
//					}
                    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(), managerId, 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(managerId, managerId, vendorId, server.getVdcId(), hostId);
                    switcherRepository.save(switcher);
                    for (PortGroup group : switcher.getGroups()) {
                        group.preSave(managerId, managerId, vendorId, switcher.getId());
                        portGroupRepository.save(group);
                    }
                    switcherMap.put(switcher.getName(), switcher.getId());
                }
                // 保存物理网卡
                utils.addCard(vendorId, hostId, managerId, "PM", JSONArray.parseArray(JSONObject.toJSONString(host.getNetcards()), NetworkCard.class), switcherMap);
                // 保存虚拟机
                List<CloudServer> cloudServers = JSONArray.parseArray(JSONObject.toJSONString(host.getServers()), CloudServer.class);
                syncServer(storeMap, oldServerMap, cloudServers, vendorId, server.getId(), vdcId, managerId,
                        server.getPowerState(), networkMap, groupMap, type, infos, vendorGuid, server.getGuid());
                // 宿主机和存储建立关系
                utils.addStore(vendorId, hostId, managerId, "PM", host.getStores(), storeMap);
                // 宿主机和网络建立关系
                utils.addNetwork(vendorId, hostId, managerId, "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(managerId);
                    node.setMenderId(managerId);
                    node.setStatus(host.getStatus());
                    clusterNodeRepository.save(node);
                }
                // cmdb添加宿主机数据
                infos.add(CmdbInfoConvertor.getInfo(server, config, null, relations, CloudProvider.VMWARE));
            }
        }
    }

    /**
     * 删除不存在的宿主机
     *
     * @param oldHostMap
     * @param managerId
     * @param infos
     * @throws Exception
     */
    private void removeHost(Map<String, Server> oldHostMap, Long managerId, 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", managerId);
            List<Switcher> switchers = switcherRepository.listByHostId(hostId);
            for (Switcher switcher : switchers) {
                portGroupRepository.removeBySwitcher(switcher.getId(), managerId);
            }
            switcherRepository.removeByHostId(hostId, managerId);
            List<CloudServer> servers = cloudServerRepository.listByHid(hostId);
            for (CloudServer server : servers) {
                snapshotRepository.removeByVm(server.getId(), managerId);
                storeHostRepository.deleteByHost(server.getId(), "VM");
                networkHostRepository.deleteByHost(server.getId(), "VM");
                networkCardRepository.removeByHost(server.getId(), "VM", managerId);
                resourceRepository.remove(server.getId(), ResourceCategory.Computer.name(),
                        ResourceCatalog.LOGICAL.name(), managerId);
                // 回收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, managerId);
            serverAssetsRepository.removeBySid(hostId);
            serverConfigRepository.removeBySid(hostId);
            resourceRepository.remove(hostId, ResourceCategory.Computer.name(), ResourceCatalog.PHYSICAL.name(),
                    managerId);
            serverRepository.remove(hostId, managerId);
            // 回收IP
            ipRepository.delete(host.getId(), "PM", host.getVendorId());
            // 删除集群节点
            clusterNodeRepository.removeByRid(host.getResourceId(), managerId);
            scsiLunRepository.removeByHostId(hostId);
        }
    }

    /**
     * 同步虚拟机下相关数据
     *
     * @param storeMap
     * @param oldServerMap
     * @param newServers
     * @param vendorId
     * @param hostId
     * @param vdcId
     * @param managerId
     * @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 managerId, 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, managerId, 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, managerId, status,
                            networkMap, groupMap, type, pools);
                    // cmdb添加虚拟机数据
                    infos.add(CmdbInfoConvertor.getInfo(cloudServer, null, relations, CloudProvider.VMWARE));
                }
            }
        }
    }

    private void removeServerCascade(CloudServer server, Long managerId, 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, managerId);
        }
        snapshotTaskService.removeByVmId(id);
        snapshotRepository.removeByVm(id, managerId);
        storeHostRepository.deleteByHost(id, "VM");
        networkHostRepository.deleteByHost(id, "VM");
        networkCardRepository.removeByHost(id, "VM", managerId);
        resourceRepository.remove(id, ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(), managerId);
        cloudServerRepository.remove(id, managerId);
        // 回收IP
        //ipRepository.delete(server.getId(), "VM", server.getVendorId());
        ipRepository.makeFreeByTarget(server.getId(), "VM", vendorId);
        serverLabelRepository.deleteByTarget(id, "VM");
    }

}
