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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.common.LocationDriver;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.*;
import com.bocloud.cmp.model.fusionsphere.*;
import com.bocloud.cmp.model.fusionsphere.sync.FusionSphereSyncModel;
import com.bocloud.cmp.provider.utils.IPAddress;
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.fusionsphere.*;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.repository.resource.fusionsphere.*;
import com.bocloud.ims.service.transporter.ResourceTransporter;
import com.google.api.client.util.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Company: 博云 www.bocloud.com
 * @ClassName: FusionSphereTransportor
 * @Description:
 * @author: zhenpingLi/李振平
 * @date: 2021/10/22 15:27
 */
@Component("fusionsphereTransporter")
@Slf4j
public class FusionSphereTransporter implements ResourceTransporter {

    @Autowired
    private VdcRepository vdcRepository;
    @Autowired
    private ClusterRepository clusterRepository;
    @Autowired
    private ServerRepository serverRepository;
    @Autowired
    private ServerConfigRepository serverConfigRepository;
    @Autowired
    private FusionSphereStorageDeviceRepository storageDeviceRepository;
    @Autowired
    private FusionSphereDeviceHostRepository deviceHostRepository;

    @Autowired
    private DataStoreRepository dataStoreRepository;
    @Autowired
    private VolumeRepository volumeRepository;
    @Autowired
    private SecurityGroupRepository securityGroupRepository;
    @Autowired
    private SecurityGroupRuleRepository securityGroupRuleRepository;
    @Autowired
    private ServerSgroupRepository serverSgroupRepository;
    @Autowired
    private SwitcherRepository switcherRepository;
    @Autowired
    private FusionSphereUpLinkRepository upLinkRepository;
    @Autowired
    private FusionSphereVlanPoolRepository vlanPoolRepository;
    @Autowired
    private PortGroupRepository portGroupRepository;
    @Autowired
    private CloudServerRepository cloudServerRepository;
    @Autowired
    private ResourceRepository resourceRepository;
    @Autowired
    private NetworkCardRepository networkCardRepository;
    @Autowired
    private SnapshotRepository snapshotRepository;
    @Autowired
    private FusionSphereHostPortRepository hostPortRepository;
    @Autowired
    private FusionSphereUpLinkPortRepository upLinkPortRepository;
    @Autowired
    private FusionSphereOsVersionRepository osVersionRepository;
    @Autowired
    private StoreHostRepository storeHostRepository;
    @Autowired
    private PoolGroupRelationRepository poolGroupRelationRepository;
    @Autowired
    private ImageRepository imageRepository;
    @Autowired
    private IpRepository ipRepository;
    @Autowired
    private IpPoolRepository ipPoolRepository;
    @Autowired
    private LocationDriver locationDriver;

    @Override
    public BocloudResult transport(CloudVendor vendor, Long userId) {
        try {
        	
        	BocloudResult bocloudResult = locationDriver.sync(vendor.getUuid());
            if(bocloudResult.isFailed()) {
            	return bocloudResult;
            }
            Assert.notNull(bocloudResult.getData(), "数据同步异常！");
            Long vendorId = vendor.getId();
        	
            if (null != bocloudResult.getData()) {
                if (cloudServerRepository.hasBuilding(vendor.getId())) {
                    return new BocloudResult(false, "该平台下有云主机正在创建，请稍后进行同步操作");
                }
                FusionSphereSyncModel model = JSONObject.parseObject(JSONObject.toJSONString(bocloudResult.getData()), FusionSphereSyncModel.class);

                log.info("starting sync vdc......");
                this.syncVdc(model.getVdcModels(), vendor.getId(), userId);
                Map<String, Vdc> vdcMap = Optional
                        .ofNullable(vdcRepository.listByVendor(vendor.getId()))
                        .map(entitys -> entitys.stream()
                                .collect(Collectors.toMap(entity -> entity.getUri(),
                                        entity -> entity)))
                        .orElse(Maps.newHashMap());
                log.info("end sync vdc !");

                log.info("starting sync OsVersion......");
                this.syncOsVersion(model.getOsVersionModels(), vendor.getId(), vdcMap);
                Map<String, FusionSphereOsVersion> osVersionMap = Optional
                        .ofNullable(osVersionRepository.listByVendorId(vendor.getId()))
                        .map(entitys -> entitys.stream()
                                .collect(Collectors.toMap(entity -> (entity.getArch() + "-" + entity.getOsVersionUuid()),
                                        entity -> entity)))
                        .orElse(Maps.newHashMap());
                log.info("end sync OsVersion !");

                log.info("starting sync cluster......");
                this.syncCluster(model.getClusterModels(), vendor.getId(), userId, vdcMap);
                Map<String, Cluster> clusterMap = Optional
                        .ofNullable(clusterRepository.listByVendor(vendor.getId()))
                        .map(entitys -> entitys.stream()
                                .collect(Collectors.toMap(entity -> entity.getClusterVal(),
                                        entity -> entity)))
                        .orElse(Maps.newHashMap());
                log.info("end sync cluster !");

                log.info("starting sync host......");
                this.syncHost(model.getHostModels(), vendor.getId(), userId, vdcMap, clusterMap);
                Map<String, Server> hostMap = Optional
                        .ofNullable(serverRepository.listByVendor(vendor.getId()))
                        .map(entitys -> entitys.stream()
                                .collect(Collectors.toMap(entity -> entity.getUuid(),
                                        entity -> entity)))
                        .orElse(Maps.newHashMap());
                Map<String, Long> hostNameMap = Optional
                        .ofNullable(serverRepository.listByVendor(vendor.getId()))
                        .map(entitys -> entitys.stream()
                                .collect(Collectors.toMap(entity -> entity.getName(),
                                        entity -> entity.getId())))
                        .orElse(Maps.newHashMap());
                Map<String, Long> hostPostUuidMap = Optional
                        .ofNullable(hostPortRepository.listByVendorId(vendor.getId()))
                        .map(entitys -> entitys.stream()
                                .collect(Collectors.toMap(entity -> entity.getPortUuid(),
                                        entity -> entity.getId())))
                        .orElse(Maps.newHashMap());

                log.info("end sync host !");

                log.info("starting storageDevice host......");
                this.syncStorageDevice(model.getStorageDeviceModels(), vendor.getId(), userId, vdcMap, hostMap);
                Map<String, FusionSphereStorageDevice> storageDeviceMap = Optional
                        .ofNullable(storageDeviceRepository.listByVendor(vendor.getId()))
                        .map(entitys -> entitys.stream()
                                .collect(Collectors.toMap(entity -> entity.getUrn(),
                                        entity -> entity)))
                        .orElse(Maps.newHashMap());
                log.info("end storageDevice host !");

                log.info("starting dataStore host......");
                this.syncDataStore(model.getDataStoreModels(), vendor.getId(), userId, vdcMap, storageDeviceMap, hostMap);
                Map<String, DataStore> dataStoreMap = Optional
                        .ofNullable(dataStoreRepository.listByVendor(vendor.getId()))
                        .map(entitys -> entitys.stream()
                                .collect(Collectors.toMap(entity -> entity.getStoreVal(),
                                        entity -> entity)))
                        .orElse(Maps.newHashMap());
                log.info("end dataStore host !");

                log.info("starting volume host......");
                this.syncVolume(model.getVolumeModels(), vendor.getId(), userId, vdcMap, dataStoreMap);
                Map<String, Volume> volumeMap = Optional
                        .ofNullable(volumeRepository.listByVendorId(vendor.getId()))
                        .map(entitys -> entitys.stream()
                                .collect(Collectors.toMap(entity -> entity.getVolumeUuid(),
                                        entity -> entity)))
                        .orElse(Maps.newHashMap());
                log.info("end volume host !");

          /* 废弃
            log.info("starting uplinkPort host......");
            this.syncUplinkPort(model.getPortModels(), vendor.getId(), userId, vdcMap, hostMap);
            log.info("end uplinkPort host !");*/


                log.info("starting sync switcher......");
                this.syncSwitcher(model.getSwitchModels(), vendor.getId(), userId, vdcMap, hostNameMap, hostPostUuidMap);
                log.info("end sync switcher !");

                log.info("starting sync SecurityGroup......");
                this.syncSecurityGroup(model.getSecurityGroupModels(), vendor, userId, vdcMap);
                Map<String, SecurityGroup> securityGroupMap = Optional
                        .ofNullable(securityGroupRepository.listByVendorId(vendor.getId()))
                        .map(entitys -> entitys.stream()
                                .collect(Collectors.toMap(entity -> entity.getGroupUuid().toLowerCase(),
                                        entity -> entity)))
                        .orElse(Maps.newHashMap());
                log.info("end sync SecurityGroup !");

                log.info("starting sync server......");
                Map<String, PortGroup> portGroupMap = Optional
                        .ofNullable(portGroupRepository.listByFcVendorId(vendor.getId()))
                        .map(entitys -> entitys.stream()
                                .collect(Collectors.toMap(entity -> entity.getGroupVal(),
                                        entity -> entity)))
                        .orElse(Maps.newHashMap());
                List<ServerModel> serverModels = model.getServerModels();

                Map<String, Ip> ipMap = Optional
                        .ofNullable(ipRepository.listByVendor(vendor.getId()))
                        .map(entitys -> entitys.stream()
                                .collect(Collectors.toMap(entity -> entity.getIp(),
                                        entity -> entity)))
                        .orElse(Maps.newHashMap());

                this.syncServer(serverModels, vendor, userId, vdcMap, volumeMap, portGroupMap, clusterMap, hostMap, securityGroupMap, ipMap);
                List<ServerModel> templateModels = serverModels.stream().filter(serverModel -> {
                    return serverModel.getIsTemplate();
                }).collect(Collectors.toList());
                Map<String, CloudServer> cloudServerMap = Optional
                        .ofNullable(cloudServerRepository.listTemplate(vendor.getId(), null))
                        .map(entitys -> entitys.stream()
                                .collect(Collectors.toMap(entity -> entity.getUri(),
                                        entity -> entity)))
                        .orElse(Maps.newHashMap());
                log.info("end sync server !");
                log.info("start sync image !");
                this.syncImage(templateModels, vendor, userId, osVersionMap, cloudServerMap);
                log.info("end sync image !");
            }
            return new BocloudResult(true, "云平台【 " + vendor.getName() + " 】数据同步成功");
        } catch (Exception e) {
            log.error("FUSIONSPHERE同步数据失败", e);
            return new BocloudResult(false, e.getMessage(), "云平台【 " + vendor.getName() + " 】数据同步失败");
        }
    }

    //同步镜像、模板
    private void syncImage(List<ServerModel> templateModels, CloudVendor vendor, Long userId, Map<String, FusionSphereOsVersion> osVersionMap, Map<String, CloudServer> cloudServerMap) {
        if (ListTool.isEmpty(templateModels)) {
            imageRepository.removeByVid(vendor.getId(), userId);
            return;
        }

        Map<String, Image> map = Optional
                .ofNullable(imageRepository.listByVendorId(vendor.getId()))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getImageUuid(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());
        //将云主机数据转换为image数据
        List<ImageModel> images = serverConvertorImage(templateModels, osVersionMap);

        for (ImageModel model : images) {
            Image entity = new Image();
            if (map.containsKey(model.getImageUuid())) {
                entity = map.get(model.getImageUuid());
                BeanUtils.copyProperties(model, entity);
                entity.setMenderId(userId);
                entity.setGmtModify(new Date());
                imageRepository.update(entity);
            } else {
                BeanUtils.copyProperties(model, entity);
                entity.setCreatorId(userId);
                entity.setGmtCreate(new Date());
                entity.setVendorId(vendor.getId());
                entity.setVendorType(vendor.getType());
                entity.setTemplateId(cloudServerMap.get(model.getImageUuid()).getId());
                entity.setCatalog("VM");
                imageRepository.save(entity);
            }
            map.remove(model.getImageUuid());
        }
        for (Map.Entry<String, Image> entry : map.entrySet()) {
            imageRepository.remove(entry.getValue().getId(), userId);
        }
    }

    private List<ImageModel> serverConvertorImage(List<ServerModel> templateModels, Map<String, FusionSphereOsVersion> osVersionMap) {
        List<ImageModel> images = Lists.newArrayList();
        templateModels.stream().forEach(
                serverModel -> {
                    ImageModel imageModel = new ImageModel();
                    imageModel.setName(serverModel.getName());
                    imageModel.setStatus("ACTIVE");
                    Optional.ofNullable(serverModel.getRemark()).ifPresent(imageModel::setRemark);

                    String key = serverModel.getArch() + "-" + serverModel.getOsVersion();
                    FusionSphereOsVersion osVersion = osVersionMap.get(key);
                    if(null != osVersion){
                        imageModel.setOsName(osVersion.getVersionDes());
                    }else{
                        imageModel.setOsName(serverModel.getOsVersion());
                    }
                    imageModel.setOsVersion(serverModel.getOsVersion());
                    imageModel.setImageUuid(serverModel.getUri());
                    imageModel.setOsCategory(serverModel.getOsCategory());
                    images.add(imageModel);
                }
        );
        return images;
    }

    //确认
    private void syncVdc(List<VDCModel> models, Long vendorId, Long userId) throws Exception {
        if (ListTool.isEmpty(models)) {
            vdcRepository.removeByVendor(vendorId, userId);
            return;
        }
        Map<String, Vdc> map = Optional
                .ofNullable(vdcRepository.listByVendor(vendorId))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getVdcVal(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());
        for (VDCModel model : models) {
            Vdc entity = new Vdc();
            if (map.containsKey(model.getVdcVal())) {
                entity = map.get(model.getVdcVal());
                BeanUtils.copyProperties(model, entity);
                entity.setMenderId(userId);
                entity.setGmtModify(new Date());
                vdcRepository.update(entity);
            } else {
                BeanUtils.copyProperties(model, entity);
                entity.setCreatorId(userId);
                entity.setGmtCreate(new Date());
                entity.setVendorId(vendorId);
                vdcRepository.save(entity);
            }
            map.remove(model.getVdcVal());
        }
        for (Map.Entry<String, Vdc> entry : map.entrySet()) {
            vdcRepository.remove(entry.getValue().getId(), userId);
        }
    }

    //确认
    private void syncCluster(List<ClusterModel> models, Long vendorId, Long userId, Map<String, Vdc> vdcMap) throws Exception {
        if (ListTool.isEmpty(models)) {
            List<Long> clusters = clusterRepository.listByVendor(vendorId).stream().map(Cluster::getId).collect(Collectors.toList());
            clusterRepository.removeByVendor(vendorId, userId);
            for (Long clusterId : clusters) {
                poolGroupRelationRepository.removeByTarget(clusterId, "Cluster");
            }
            return;
        }
        Map<String, Cluster> map = Optional
                .ofNullable(clusterRepository.listByVendor(vendorId))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getClusterVal(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());
        for (ClusterModel model : models) {
            Cluster entity = new Cluster();
            if (map.containsKey(model.getClusterVal())) {
                entity = map.get(model.getClusterVal());
                BeanUtils.copyProperties(model, entity);
                entity.setMenderId(userId);
                entity.setGmtModify(new Date());
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                clusterRepository.update(entity);
            } else {
                BeanUtils.copyProperties(model, entity);
                entity.setCreatorId(userId);
                entity.setGmtCreate(new Date());
                entity.setVendorId(vendorId);
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                clusterRepository.save(entity);
            }
            map.remove(model.getClusterVal());
        }
        for (Map.Entry<String, Cluster> entry : map.entrySet()) {
            clusterRepository.remove(entry.getValue().getId(), userId);
            poolGroupRelationRepository.removeByTarget(entry.getValue().getId(), "Cluster");
        }
    }

    //确认
    private void syncOsVersion(List<FusionSphereOsVersionModel> models, Long vendorId, Map<String, Vdc> vdcMap) throws Exception {
        if (ListTool.isEmpty(models)) {
            osVersionRepository.deleteByVendorId(vendorId);
            return;
        }
        Map<String, FusionSphereOsVersion> map = Optional
                .ofNullable(osVersionRepository.listByVendorId(vendorId))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> (entity.getArch() + "-" + entity.getOsVersionUuid()),
                                entity -> entity)))
                .orElse(Maps.newHashMap());
        String key;
        for (FusionSphereOsVersionModel model : models) {
            FusionSphereOsVersion entity = new FusionSphereOsVersion();
            key = model.getArch() + "-" + model.getOsVersionUuid();
            if (map.containsKey(key)) {
                entity = map.get(key);
                BeanUtils.copyProperties(model, entity);
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                osVersionRepository.update(entity);
            } else {
                BeanUtils.copyProperties(model, entity);
                entity.setVendorId(vendorId);
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                osVersionRepository.save(entity);
            }
            map.remove(key);
        }
        for (Map.Entry<String, FusionSphereOsVersion> entry : map.entrySet()) {
            osVersionRepository.delete(entry.getValue().getId());
        }
    }


    //确认
    private void syncHost(List<HostModel> models, Long vendorId, Long userId, Map<String, Vdc> vdcMap, Map<String, Cluster> clusterMap) throws Exception {
        if (ListTool.isEmpty(models)) {
            List<Long> hosts = serverRepository.listByVendor(vendorId).stream().map(Server::getId).collect(Collectors.toList());
            serverRepository.removeByVendor(vendorId, userId);
            hostPortRepository.removeByVendorId(vendorId, userId);
            for (Long hostId : hosts) {
                poolGroupRelationRepository.removeByTarget(hostId, "Host");
            }
            return;
        }
        Map<String, Server> map = Optional
                .ofNullable(serverRepository.listByVendor(vendorId))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getUuid(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());
        for (HostModel model : models) {
            Server entity = new Server();
            if (map.containsKey(model.getUuid())) {
                entity = map.get(model.getUuid());
                BeanUtils.copyProperties(model, entity, "id");
                entity.setServiceIp(model.getHostIp());
                entity.setArch(model.getArch());
                entity.setMenderId(userId);
                entity.setGmtModify(new Date());
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                Optional.ofNullable(model.getClusterUuid()).map(clusterUuid -> clusterMap.get(clusterUuid).getId()).ifPresent(entity::setClusterId);
                serverRepository.update(entity);
            } else {
                BeanUtils.copyProperties(model, entity);
                entity.setServiceIp(model.getHostIp());
                entity.setArch(model.getArch());
                entity.setCreatorId(userId);
                entity.setGmtCreate(new Date());
                entity.setVendorId(vendorId);
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                Optional.ofNullable(model.getClusterUuid()).map(clusterUuid -> clusterMap.get(clusterUuid).getId()).ifPresent(entity::setClusterId);
                serverRepository.save(entity);
            }
            map.remove(model.getUuid());

            //同步主机配置
            this.syncServerConfig(model, entity);
            //同步服务器网口
            this.syncHostPort(model.getHostPortModels(), entity);
        }
        for (Map.Entry<String, Server> entry : map.entrySet()) {
            serverRepository.remove(entry.getValue().getId(), userId);
            hostPortRepository.removeByHost(entry.getValue().getId(), userId);
            poolGroupRelationRepository.removeByTarget(entry.getValue().getId(), "Host");
        }
    }

    //确认
    private void syncServerConfig(HostModel hostModel, Server server) {
        serverConfigRepository.removeBySid(server.getId());
        ServerConfig entity = new ServerConfig();
        entity.setServerId(server.getId());
        entity.setCpuAmount(hostModel.getCpuNum());
        entity.setCpuHz(hostModel.getCpuHz());
        entity.setCpuUsed(hostModel.getCpuUsed());
        entity.setMemoryCapacity(hostModel.getMemTotal());
        entity.setMemUsed(hostModel.getMemUsed());
        serverConfigRepository.save(entity);
    }

    //确认
    private void syncHostPort(List<HostPortModel> models, Server server) throws Exception {
        if (ListTool.isEmpty(models)) {
            hostPortRepository.removeByHost(server.getId(), server.getCreatorId());
            return;
        }
        Map<String, FusionSphereHostPort> map = Optional
                .ofNullable(hostPortRepository.listByHost(server.getId()))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getPortUuid(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());
        for (HostPortModel model : models) {
            FusionSphereHostPort entity = new FusionSphereHostPort();
            if (map.containsKey(model.getPortUuid())) {
                entity = map.get(model.getPortUuid());
                BeanUtils.copyProperties(model, entity);
                entity.setHostId(server.getId());
                entity.setMenderId(server.getMenderId());
                entity.setVendorId(server.getVendorId());
                entity.setGmtModify(new Date());
                hostPortRepository.update(entity);
            } else {
                BeanUtils.copyProperties(model, entity);
                entity.setHostId(server.getId());
                entity.setCreatorId(server.getCreatorId());
                entity.setGmtCreate(new Date());
                entity.setVendorId(server.getVendorId());
                hostPortRepository.save(entity);
            }
            map.remove(model.getPortUuid());
        }
        for (Map.Entry<String, FusionSphereHostPort> entry : map.entrySet()) {
            hostPortRepository.remove(entry.getValue().getId(), server.getCreatorId());
        }
        //同步物理口绑定关系
        this.syncHostPortRelation(models, server);
    }

    private void syncHostPortRelation(List<HostPortModel> models, Server server) throws Exception {
        Map<String, FusionSphereHostPort> map = Optional
                .ofNullable(hostPortRepository.listByHost(server.getId()))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getPortUuid(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());
        //所有被绑定的物理口
        List<HostPortModel> upLinkPortModels = models.stream().filter(portModel -> portModel.getParentUuid() != null).collect(Collectors.toList());
        for (HostPortModel model : upLinkPortModels) {
            FusionSphereHostPort hostPortEntity = map.get(model.getPortUuid());
            FusionSphereHostPort hostPortParent = map.get(model.getParentUuid());
            if (null != hostPortEntity && null != hostPortParent) {
                hostPortEntity.setParentId(hostPortParent.getId());
                hostPortRepository.update(hostPortEntity);
            }
        }
    }


    //确认
    private void syncStorageDevice(List<StorageDeviceModel> models, Long vendorId, Long userId, Map<String, Vdc> vdcMap, Map<String, Server> hostMap) throws Exception {
        if (ListTool.isEmpty(models)) {
            storageDeviceRepository.removeByVendor(vendorId, userId);
            return;
        }
        Map<String, FusionSphereStorageDevice> map = Optional
                .ofNullable(storageDeviceRepository.listByVendor(vendorId))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getUrn(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());
        for (StorageDeviceModel model : models) {
            FusionSphereStorageDevice entity = new FusionSphereStorageDevice();
            if (map.containsKey(model.getUrn())) {
                entity = map.get(model.getUrn());
                BeanUtils.copyProperties(model, entity);
                entity.setMenderId(userId);
                entity.setGmtModify(new Date());
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                storageDeviceRepository.update(entity);
            } else {
                BeanUtils.copyProperties(model, entity);
                entity.setCreatorId(userId);
                entity.setGmtCreate(new Date());
                entity.setVendorId(vendorId);
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                storageDeviceRepository.save(entity);
            }
            map.remove(model.getUrn());
            this.deviceHostRelation(model, entity, hostMap);
        }
        for (Map.Entry<String, FusionSphereStorageDevice> entry : map.entrySet()) {
            storageDeviceRepository.remove(entry.getValue().getId(), userId);
        }
    }

    //确认
    private void deviceHostRelation(StorageDeviceModel deviceModel, FusionSphereStorageDevice device, Map<String, Server> hostMap) {
        deviceHostRepository.removeByDeviceId(device.getId());
        for (HostModel hostModel : deviceModel.getHostModels()) {
            FusionSphereDeviceHost entity = new FusionSphereDeviceHost();
            entity.setDeviceId(device.getId());
            entity.setHostId(hostMap.get(hostModel.getUuid()).getId());
            deviceHostRepository.save(entity);
        }
    }

    //确认
    private void syncDataStore(List<DataStoreModel> models, Long vendorId, Long userId, Map<String, Vdc> vdcMap, Map<String, FusionSphereStorageDevice> storageDeviceMap, Map<String, Server> hostMap) throws Exception {
        if (ListTool.isEmpty(models)) {
            List<Long> stores = dataStoreRepository.listByVendor(vendorId).stream().map(DataStore::getId).collect(Collectors.toList());
            dataStoreRepository.removeByVendor(vendorId, userId);
            storeHostRepository.removeByVendor(vendorId);
            for (Long storeId : stores) {
                poolGroupRelationRepository.removeByTarget(storeId, "Storage");
            }
            return;
        }
        Map<String, DataStore> map = Optional
                .ofNullable(dataStoreRepository.listByVendor(vendorId))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getStoreVal(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());
        //无论是否存在云主机与存储的关系，每次全部重新save数据
        storeHostRepository.removeByVendor(vendorId);
        for (DataStoreModel model : models) {
            DataStore entity = new DataStore();
            if (map.containsKey(model.getStoreVal())) {
                entity = map.get(model.getStoreVal());
                BeanUtils.copyProperties(model, entity);
                entity.setMenderId(userId);
                entity.setGmtModify(new Date());
                Optional.ofNullable(model.getCapacity()).map(capacity -> capacity.longValue()).ifPresent(entity::setCapacity);
                Optional.ofNullable(model.getFreeSpace()).map(freeSpace -> freeSpace.longValue()).ifPresent(entity::setFreeSpace);
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                Optional.ofNullable(model.getStoreDeviceUuid()).map(storeDeviceUuid -> storageDeviceMap.get(storeDeviceUuid).getId()).ifPresent(entity::setStorageDeviceId);
                dataStoreRepository.update(entity);
            } else {
                BeanUtils.copyProperties(model, entity);
                entity.setCreatorId(userId);
                entity.setGmtCreate(new Date());
                entity.setVendorId(vendorId);
                Optional.ofNullable(model.getCapacity()).map(capacity -> capacity.longValue()).ifPresent(entity::setCapacity);
                Optional.ofNullable(model.getFreeSpace()).map(freeSpace -> freeSpace.longValue()).ifPresent(entity::setFreeSpace);
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                Optional.ofNullable(model.getStoreDeviceUuid()).map(storeDeviceUuid -> storageDeviceMap.get(storeDeviceUuid).getId()).ifPresent(entity::setStorageDeviceId);
                dataStoreRepository.save(entity);
            }
            List<String> hostUuids = model.getHostUuids();
            if (!ListTool.isEmpty(hostUuids)) {
                for (String hostUuid : hostUuids) {
                    StoreHost storeHost = new StoreHost();
                    storeHost.setStoreId(entity.getId());
                    storeHost.setCategory("PM");
                    storeHost.setVendorId(vendorId);
                    storeHost.setVhostId(hostMap.get(hostUuid).getId());
                    storeHostRepository.save(storeHost);
                }
            }
            map.remove(model.getStoreVal());
        }
        for (Map.Entry<String, DataStore> entry : map.entrySet()) {
            dataStoreRepository.remove(entry.getValue().getId(), userId);
            poolGroupRelationRepository.removeByTarget(entry.getValue().getId(), "Storage");
        }
    }

    //确认
    private void syncVolume(List<VolumeModel> models, Long vendorId, Long userId, Map<String, Vdc> vdcMap, Map<String, DataStore> dataStoreMap) throws Exception {
        if (ListTool.isEmpty(models)) {
            volumeRepository.removeByVid(vendorId, userId);
            return;
        }
        Map<String, Volume> map = Optional
                .ofNullable(volumeRepository.listByVendorId(vendorId))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getVolumeUuid(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());
        for (VolumeModel model : models) {
            Volume entity = new Volume();
            if (map.containsKey(model.getVolumeUuid())) {
                entity = map.get(model.getVolumeUuid());
                BeanUtils.copyProperties(model, entity);
                entity.setMenderId(userId);
                entity.setGmtModify(new Date());
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                Optional.ofNullable(model.getDataStoreUuid()).map(dataStoreUuid -> dataStoreMap.get(dataStoreUuid).getId()).ifPresent(entity::setDataStoreId);
                volumeRepository.update(entity);
            } else {
                BeanUtils.copyProperties(model, entity);
                entity.setCreatorId(userId);
                entity.setGmtCreate(new Date());
                entity.setVendorId(vendorId);
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                Optional.ofNullable(model.getDataStoreUuid()).map(dataStoreUuid -> dataStoreMap.get(dataStoreUuid).getId()).ifPresent(entity::setDataStoreId);
                volumeRepository.save(entity);
            }
            map.remove(model.getVolumeUuid());
        }
        for (Map.Entry<String, Volume> entry : map.entrySet()) {
            volumeRepository.remove(entry.getValue().getId(), userId);
        }
    }

/*     废弃
    private void syncUplinkPort(List<PortModel> models, Long vendorId, Long userId, Map<String, Vdc> vdcMap, Map<String, Server> hostMap) throws Exception {
        if (ListTool.isEmpty(models)) {
            portRepository.removeByVid(vendorId, userId);
            return;
        }
        Map<String, Port> map = Optional
                .ofNullable(portRepository.listByVid(vendorId))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getPortUuid(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());
        for (PortModel model : models) {
            Port entity = new Port();
            if (map.containsKey(model.getPortUuid())) {
                entity = map.get(model.getPortUuid());
                BeanUtils.copyProperties(model, entity);
                entity.setMenderId(userId);
                entity.setGmtModify(new Date());
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                Optional.ofNullable(model.getDeviceUuid()).map(deviceUuid -> hostMap.get(deviceUuid).getId()).ifPresent(entity::setDeviceId);
                portRepository.update(entity);
            } else {
                BeanUtils.copyProperties(model, entity);
                entity.setCreatorId(userId);
                entity.setGmtCreate(new Date());
                entity.setVendorId(vendorId);
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                Optional.ofNullable(model.getDeviceUuid()).map(deviceUuid -> hostMap.get(deviceUuid).getId()).ifPresent(entity::setDeviceId);
                portRepository.save(entity);
            }
            map.remove(model.getPortUuid());
        }
        for (Map.Entry<String, Port> entry : map.entrySet()) {
            portRepository.remove(entry.getValue().getId(), userId);
        }
    }*/

    //确认
    private void syncSwitcher(List<SwitchModel> models, Long vendorId, Long userId, Map<String, Vdc> vdcMap, Map<String, Long> hostNameMap, Map<String, Long> hostPostNameMap) throws Exception {
        if (ListTool.isEmpty(models)) {
            List<Switcher> switchers = switcherRepository.listByVid(vendorId);
            switcherRepository.removeByVid(vendorId, userId);
            portGroupRepository.removeByVid(vendorId, userId);
            switchers.stream().forEach(
                    switcher -> {
                        upLinkRepository.deleteBySwitcherId(switcher.getId());
                        upLinkPortRepository.deleteBySwitcherId(switcher.getId());
                        vlanPoolRepository.deleteBySwitcherId(switcher.getId());
                    }
            );
            return;
        }
        Map<String, Switcher> map = Optional
                .ofNullable(switcherRepository.listByVid(vendorId))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getSwitcherVal(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());
        for (SwitchModel model : models) {
            Switcher entity = new Switcher();
            if (map.containsKey(model.getSwitcherVal())) {
                entity = map.get(model.getSwitcherVal());
                BeanUtils.copyProperties(model, entity);
                entity.setMenderId(userId);
                entity.setGmtModify(new Date());
                entity.setVendorId(vendorId);
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                switcherRepository.update(entity);
            } else {
                BeanUtils.copyProperties(model, entity);
                entity.setCreatorId(userId);
                entity.setGmtCreate(new Date());
                entity.setVendorId(vendorId);
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                switcherRepository.save(entity);
            }
            map.remove(model.getSwitcherVal());

            this.syncSwitcherSonResource(model, entity, hostNameMap, hostPostNameMap);
            this.syncPortGroup(model.getGroups(), entity, userId);
        }
        for (Map.Entry<String, Switcher> entry : map.entrySet()) {
            switcherRepository.remove(entry.getValue().getId(), userId);
            portGroupRepository.removeBySwitcher(entry.getValue().getId(), userId);
            upLinkRepository.deleteBySwitcherId(entry.getValue().getId());
            upLinkPortRepository.deleteBySwitcherId(entry.getValue().getId());
            vlanPoolRepository.deleteBySwitcherId(entry.getValue().getId());
        }
    }

    //确认
    private void syncSwitcherSonResource(SwitchModel switchModel, Switcher switcher, Map<String, Long> hostNameMap, Map<String, Long> hostPostNameMap) {
        upLinkRepository.deleteBySwitcherId(switcher.getId());
        upLinkPortRepository.deleteBySwitcherId(switcher.getId());
        vlanPoolRepository.deleteBySwitcherId(switcher.getId());

        if (!ListTool.isEmpty(switchModel.getUpLinkModels())) {
            for (FusionSphereUpLinkModel upLinkModel : switchModel.getUpLinkModels()) {
                FusionSphereUpLink upLink = new FusionSphereUpLink();
                upLink.setStatus(upLinkModel.getStatus());
                upLink.setSwitcherId(switcher.getId());
                upLink.setVendorId(switcher.getVendorId());
                Optional.ofNullable(hostNameMap.get(upLinkModel.getHostName())).ifPresent(upLink::setHostId);
                //可以按照uuid
                Optional.ofNullable(hostPostNameMap.get(upLinkModel.getPortUuid())).ifPresent(upLink::setPortId);
                upLinkRepository.save(upLink);
            }
        }
//        for (FusionSphereUpLinkPortModel linkPortModel : switchModel.getUpLinkPortModels()) {
//            FusionSphereUpLinkPort linkPort = new FusionSphereUpLinkPort();
//            BeanUtils.copyProperties(linkPortModel, linkPort);
//            linkPort.setSwitcherId(switcher.getId());
//            Optional.ofNullable(hostNameMap.get(linkPortModel.getHostName())).ifPresent(linkPort::setHostId);
//            //必须按照名称
//            Optional.ofNullable(hostPostNameMap.get(linkPortModel.getPortName())).ifPresent(linkPort::setPortId);
//            upLinkPortRepository.save(linkPort);
//        }
        if (!ListTool.isEmpty(switchModel.getVlanPoolModels())) {
            for (FusionSphereVlanPoolModel vlanPoolModel : switchModel.getVlanPoolModels()) {
                FusionSphereVlanPool vlanPool = new FusionSphereVlanPool();
                vlanPool.setStartVlanId(vlanPoolModel.getStartVlanId());
                vlanPool.setEndVlanId(vlanPoolModel.getEndVlanId());
                vlanPool.setSwitcherId(switcher.getId());
                vlanPoolRepository.save(vlanPool);
            }
        }
    }

    //确认
    private void syncPortGroup(List<PortGroupModel> models, Switcher switcher, Long userId) throws Exception {

        if (ListTool.isEmpty(models)) {
            portGroupRepository.removeBySwitcher(switcher.getId(), userId);
            return;
        }
        Map<String, PortGroup> map = Optional
                .ofNullable(portGroupRepository.listBySwitcher(switcher.getId()))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getGroupVal(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());
        for (PortGroupModel model : models) {
            PortGroup entity = new PortGroup();
            if (map.containsKey(model.getGroupVal())) {
                entity = map.get(model.getGroupVal());
                BeanUtils.copyProperties(model, entity);
                entity.setMenderId(userId);
                entity.setGmtModify(new Date());
                entity.setSwitcherId(switcher.getId());
                entity.setVendorId(switcher.getVendorId());
                portGroupRepository.update(entity);
            } else {
                BeanUtils.copyProperties(model, entity);
                entity.setCreatorId(userId);
                entity.setGmtCreate(new Date());
                entity.setVendorId(switcher.getVendorId());
                entity.setSwitcherId(switcher.getId());
                portGroupRepository.save(entity);
            }
            map.remove(model.getGroupVal());
        }
        for (Map.Entry<String, PortGroup> entry : map.entrySet()) {
            portGroupRepository.remove(entry.getValue().getId(), userId);
        }
    }

    //确认
    private void syncSecurityGroup(List<SecurityGroupModel> models, CloudVendor vendor, Long userId, Map<String, Vdc> vdcMap) throws Exception {
        if (ListTool.isEmpty(models)) {
            securityGroupRepository.removeByVid(vendor.getId(), userId);
            return;
        }
        Map<String, SecurityGroup> map = Optional
                .ofNullable(securityGroupRepository.listByVendorId(vendor.getId()))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getGroupUuid().toLowerCase(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());
        for (SecurityGroupModel model : models) {
            SecurityGroup entity = new SecurityGroup();
            if (map.containsKey(model.getGroupUuid().toLowerCase())) {
                entity = map.get(model.getGroupUuid().toLowerCase());
                BeanUtils.copyProperties(model, entity);
                entity.setMenderId(userId);
                Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
                securityGroupRepository.update(entity);
                securityGroupRuleRepository.removeBySgId(entity.getId(), userId);
                for (SecurityGroupRuleModel securityGroupRuleModel : model.getModels()) {
                    SecurityGroupRule securityGroupRule = new SecurityGroupRule();
                    BeanUtils.copyProperties(securityGroupRuleModel, securityGroupRule);
                    securityGroupRule.setCreatorId(userId);
                    securityGroupRule.setVendorId(vendor.getId());
                    securityGroupRule.setGroupId(entity.getId());
                    securityGroupRule.setGroupUuid(entity.getGroupUuid());
                    securityGroupRule.setDefaultRule(securityGroupRuleModel.getDefaultRule());
                    securityGroupRuleRepository.save(securityGroupRule);
                }
                map.remove(model.getGroupUuid().toLowerCase());
                continue;
            }
            BeanUtils.copyProperties(model, entity);
            entity.preSave(userId, userId, vendor.getId(), 0L, 0L);
            Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
            securityGroupRepository.save(entity);
            map.remove(model.getGroupUuid().toLowerCase());
            securityGroupRuleRepository.removeBySgId(entity.getId(), userId);
            for (SecurityGroupRuleModel securityGroupRuleModel : model.getModels()) {
                SecurityGroupRule securityGroupRule = new SecurityGroupRule();
                BeanUtils.copyProperties(securityGroupRuleModel, securityGroupRule);
                securityGroupRule.setCreatorId(userId);
                securityGroupRule.setVendorId(vendor.getId());
                securityGroupRule.setGroupId(entity.getId());
                securityGroupRule.setGroupUuid(entity.getGroupUuid());
                securityGroupRule.setDefaultRule(securityGroupRuleModel.getDefaultRule());
                securityGroupRuleRepository.save(securityGroupRule);
            }
        }
        // 删除不存在的安全组
        for (Map.Entry<String, SecurityGroup> entry : map.entrySet()) {
            securityGroupRuleRepository.removeBySgId(entry.getValue().getId(), userId);
            securityGroupRepository.remove(entry.getValue().getId(), userId);
        }
    }

    //确认
    private void syncServer(List<ServerModel> models, CloudVendor vendor, Long userId, Map<String, Vdc> vdcMap,
                            Map<String, Volume> volumeMap, Map<String, PortGroup> portGroupMap, Map<String, Cluster> clusterMap,
                            Map<String, Server> hostMap, Map<String, SecurityGroup> groupMap, Map<String, Ip> ipMap) throws Exception {
        if (ListTool.isEmpty(models)) {
            List<CloudServer> cloudServers = cloudServerRepository.listVid(vendor.getId());
            for (CloudServer server : cloudServers) {
                ipRepository.makeFreeByTarget(server.getId(), "VM", server.getVendorId());
            }
            cloudServerRepository.removeByVid(vendor.getId(), userId);
            resourceRepository.removeByVid(vendor.getId(), userId);
            snapshotRepository.removeByVid(vendor.getId(), userId);
            return;
        }
        Map<String, CloudServer> map = Optional
                .ofNullable(cloudServerRepository.listVid(vendor.getId()))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getInstanceId(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());

        for (ServerModel model : models) {
            this.updateOrSaveServer(vendor, userId, vdcMap, volumeMap, portGroupMap, clusterMap, hostMap, groupMap, ipMap, map, model);
        }
        for (Map.Entry<String, CloudServer> entry : map.entrySet()) {
            CloudServer server = entry.getValue();
            cloudServerRepository.remove(server.getId(), userId);
            resourceRepository.remove(server.getId(), ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(), userId);
            serverSgroupRepository.removeBySid(server.getId());
            snapshotRepository.removeByVm(server.getId(), userId);
            networkCardRepository.removeByServerId(server.getId(), userId);
            ipRepository.makeFreeByTarget(server.getId(), "VM", server.getVendorId());
        }
    }

    public void updateOrSaveServer(CloudVendor vendor, Long userId, Map<String, Vdc> vdcMap,
                                   Map<String, Volume> volumeMap, Map<String, PortGroup> portGroupMap,
                                   Map<String, Cluster> clusterMap, Map<String, Server> hostMap,
                                   Map<String, SecurityGroup> groupMap, Map<String, Ip> ipMap,
                                   Map<String, CloudServer> map, ServerModel model) throws Exception {
        CloudServer entity = new CloudServer();
        if (map.containsKey(model.getInstanceId())) {
            entity = map.get(model.getInstanceId());
            model.setPassword(entity.getPassword());
            BeanUtils.copyProperties(model, entity);
            entity.setMenderId(userId);
            entity.setGmtModify(new Date());
            entity.setGmtVmCreate(model.getGmtVmCreate());
            entity.setVendorType(vendor.getType());
            entity.setIsTemplate(model.getIsTemplate());
            entity.setProps(model.getProps());
            // 安全组
            if (!CollectionUtils.isEmpty(model.getSecurityGroups())) {
                entity.setSecurityGroupId(JSON.toJSONString(model.getSecurityGroups()));
            }
            Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
            if (!StringUtils.isEmpty(model.getHostUuid())) {
                entity.setHostId(hostMap.get(model.getHostUuid()).getId());
            }
            if (!StringUtils.isEmpty(model.getClusterUuid())) {
                entity.setClusterId(clusterMap.get(model.getClusterUuid()).getId());
            }
            cloudServerRepository.update(entity);
        } else {
            BeanUtils.copyProperties(model, entity);
            entity.setCreatorId(userId);
            entity.setGmtCreate(new Date());
            entity.setVendorId(vendor.getId());
            entity.setVendorType(vendor.getType());
            entity.setProps(model.getProps());
            entity.setTenantId(0L);
            entity.setProjectId(0L);
            entity.setIsTemplate(model.getIsTemplate());
            entity.setRecycle(false);
            // 安全组
            if (!CollectionUtils.isEmpty(model.getSecurityGroups())) {
                entity.setSecurityGroupId(JSON.toJSONString(model.getSecurityGroups()));
            }
            Optional.ofNullable(model.getVdcUri()).map(uri -> vdcMap.get(uri).getId()).ifPresent(entity::setVdcId);
            if (!StringUtils.isEmpty(model.getHostUuid())) {
                entity.setHostId(hostMap.get(model.getHostUuid()).getId());
            }
            if (!StringUtils.isEmpty(model.getClusterUuid())) {
                entity.setClusterId(clusterMap.get(model.getClusterUuid()).getId());
            }
            cloudServerRepository.save(entity);
        }
        map.remove(model.getInstanceId());
        //更新云主机和硬盘关系
        updateVolume(model, entity, volumeMap);
        //更新云主机和网卡关系
        updateNics(model, entity, userId, portGroupMap, groupMap);
        // 更新云主机绑定的安全组
        updateSGroup(model, entity, groupMap);
        // 更新资源表
        updateResource(entity, vendor, userId);
        // 更新快照表
        updateSnapshot(model.getSnapshots(), entity.getId(), vendor, userId, 0L);
        //更新ip关系
        UpdateIp(entity, ipMap);
    }

    private void UpdateIp(CloudServer entity, Map<String, Ip> ipMap) {
        if (entity.getIsTemplate()) {
            ipRepository.makeFreeByTarget(entity.getId(), "VM", entity.getVendorId());
        }
        if (!StringUtils.isEmpty(entity.getPrivateIps())) {
            List<String> vmIps = JSONObject.parseArray(entity.getPrivateIps(), String.class);
            for (String vmIp : vmIps) {
                if (vmIp.equals("0.0.0.0")) {
                    ipRepository.makeFreeByTarget(entity.getId(), "VM", entity.getVendorId());
                    continue;
                }
                if (ipMap.containsKey(vmIp)) {
                    Ip ip = ipMap.get(vmIp);
                    ip.setCatalog("VM");
                    ip.setTarget(entity.getId());
                    ip.setVendorId(entity.getVendorId());
                    ip.setStatus(Ip.IpStatus.used);
                    ipRepository.update(ip);
                } else {
                    List<IpPool> pools = ipPoolRepository.listByIpVersion(null);
                    Ip ip = ipRepository.checkExist(vmIp, null, entity.getVendorId());
                    if (null == ip) {
                        ip = new Ip(vmIp, null, null, null, entity.getVendorId(), IDFactory.instance().uuid(),
                                null, Ip.IpStatus.used);
                        ip.setCatalog("VM");
                        ip.setTarget(entity.getId());
                        ipRepository.save(ip);
                    } else {
                        ip.setTarget(entity.getId());
                        ip.setStatus(Ip.IpStatus.used);
                        ip.setCatalog("VM");
                        ip.setVendorId(entity.getVendorId());
                        ipRepository.update(ip);
                    }
                }
            }
        }
    }

    //暂时获取快照基本信息，详细信息需要detail才可以拿到
    private void updateSnapshot(List<SnapshotModel> snapshotModels, Long serverId, CloudVendor vendor, Long userId, Long parentId) {
        if (CollectionUtils.isEmpty(snapshotModels)) {
            snapshotRepository.removeByVm(serverId, userId);
            return;
        }

        Map<String, Snapshot> map = Optional
                .ofNullable(snapshotRepository.listByVMidAndParentId(serverId, parentId))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getSnapshotUuid(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());
        Map<String, Snapshot> snapshotMap = new HashMap<>();
        for (SnapshotModel model : snapshotModels) {
            Snapshot entity = new Snapshot();
            if (map.containsKey(model.getSnapshotUuid())) {
                entity = map.get(model.getSnapshotUuid());
                BeanUtils.copyProperties(model, entity);
                entity.setVmId(serverId);
                entity.setMenderId(userId);
                entity.setGmtModify(new Date());
                entity.setVendorId(vendor.getId());
                entity.setParentId(parentId);
                snapshotRepository.update(entity);
            } else {
                BeanUtils.copyProperties(model, entity);
                entity.setVmId(serverId);
                entity.setVendorId(vendor.getId());
                entity.setCreatorId(userId);
                entity.setGmtCreate(new Date());
                entity.setParentId(parentId);
                snapshotRepository.save(entity);
            }
            //存在子快照
            if (!ListTool.isEmpty(model.getChildSnapshots())) {
                updateSnapshot(model.getChildSnapshots(), serverId, vendor, userId, entity.getId());
            } else {//不存在子快照时，需要根据云主机id和此层id进行子快照删除
                removeByVmAndParentId(serverId, userId, entity.getId());
            }
            map.remove(model.getSnapshotUuid());
        }
        for (Map.Entry<String, Snapshot> entry : map.entrySet()) {
            snapshotRepository.remove(entry.getValue().getId(), userId);
            removeByVmAndParentId(serverId, userId, entry.getValue().getId());
        }
    }

    private void removeByVmAndParentId(Long serverId, Long userId, Long snapshotId) {
        List<Snapshot> snapshots = snapshotRepository.listByVMidAndParentId(serverId, snapshotId);
        if (!ListTool.isEmpty(snapshots)) {
            snapshots.stream().forEach(
                    snapshot -> snapshotRepository.remove(snapshot.getId(), userId)
            );
        }
    }

    //确认
    private void updateVolume(ServerModel model, CloudServer entity, Map<String, Volume> volumeMap) {
        if (CollectionUtils.isEmpty(model.getDiskDevices())) {
            return;
        }
        Map<String, Volume> map = Optional
                .ofNullable(volumeRepository.listByServerId(entity.getId()))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity1 -> entity1.getVolumeUuid(),
                                entity1 -> entity1)))
                .orElse(Maps.newHashMap());
        for (VolumeModel svModel : model.getDiskDevices()) {
            Volume volume = volumeMap.get(svModel.getVolumeUuid());
            if (null != volume) {
                volume.setStatus("IN_USE");
                volume.setPciType(svModel.getPciType());
                volume.setSequenceNum(svModel.getSequenceNum());
                volume.setIoMode(svModel.getIoMode());
                volume.setAccessMode(svModel.getAccessMode());
                volume.setBootVolume(svModel.getBootVolume());
                volume.setServerId(entity.getId());
                volume.setInstanceId(model.getInstanceId());
                volumeRepository.update(volume);
            }
            if (map.containsKey(svModel.getVolumeUuid())) {
                map.remove(svModel.getVolumeUuid());
            }
        }
        for (Map.Entry<String, Volume> entry : map.entrySet()) {
            Volume volume = entry.getValue();
            volume.setStatus("AVAILABLE");
            volume.setPciType(null);
            volume.setSequenceNum(null);
            volume.setIoMode(null);
            volume.setAccessMode(null);
            volume.setBootVolume(null);
            volume.setServerId(null);
            volume.setInstanceId(null);
            volumeRepository.update(volume);
        }
    }

    //确认
    private void updateNics(ServerModel serverModel, CloudServer cloudServer, Long userId, Map<String, PortGroup> portGroupMap, Map<String, SecurityGroup> groupMap) throws Exception {
        if (CollectionUtils.isEmpty(serverModel.getNetworkCards())) {
            networkCardRepository.removeByServerId(cloudServer.getId(), userId);
            return;
        }
        Map<String, NetworkCard> map = Optional
                .ofNullable(networkCardRepository.listByServerId(cloudServer.getId()))
                .map(entitys -> entitys.stream()
                        .collect(Collectors.toMap(entity -> entity.getNetworkcardUuid(),
                                entity -> entity)))
                .orElse(Maps.newHashMap());

        for (NetworkCardModel model : serverModel.getNetworkCards()) {
            NetworkCard entity = new NetworkCard();
            if (map.containsKey(model.getNetworkcardUuid())) {
                entity = map.get(model.getNetworkcardUuid());
                BeanUtils.copyProperties(model, entity);
                entity.setServerId(cloudServer.getId());
                entity.setNumber(model.getSequenceNum());
                entity.setVringbuf(model.getVringbuf());
                entity.setQueues(model.getQueues());
                entity.setMenderId(userId);
                entity.setGmtModify(new Date());
                Optional.ofNullable(model.getPortGroupUuid()).map(portGroupUuid -> portGroupMap.get(portGroupUuid).getId()).ifPresent(entity::setPortGroupId);
                Optional.ofNullable(model.getPortGroupUuid()).map(portGroupUuid -> portGroupMap.get(portGroupUuid).getSwitcherId()).ifPresent(entity::setSwitcherId);
                Optional.ofNullable(model.getSecurityGroupUuid()).map(securityGroupUuid -> groupMap.get(securityGroupUuid).getId()).ifPresent(entity::setSecurityGroupId);
                networkCardRepository.update(entity);
            } else {
                BeanUtils.copyProperties(model, entity);
                entity.setNumber(model.getSequenceNum());
                entity.setServerId(cloudServer.getId());
                entity.setVendorId(cloudServer.getVendorId());
                entity.setVringbuf(model.getVringbuf());
                entity.setQueues(model.getQueues());
                entity.setCreatorId(userId);
                entity.setGmtCreate(new Date());
                Optional.ofNullable(model.getPortGroupUuid()).map(portGroupUuid -> portGroupMap.get(portGroupUuid).getId()).ifPresent(entity::setPortGroupId);
                Optional.ofNullable(model.getPortGroupUuid()).map(portGroupUuid -> portGroupMap.get(portGroupUuid).getSwitcherId()).ifPresent(entity::setSwitcherId);
                Optional.ofNullable(model.getSecurityGroupUuid()).map(securityGroupUuid -> groupMap.get(securityGroupUuid).getId()).ifPresent(entity::setSecurityGroupId);
                networkCardRepository.save(entity);
            }
            map.remove(model.getNetworkcardUuid());
        }
        for (Map.Entry<String, NetworkCard> entry : map.entrySet()) {
            networkCardRepository.remove(entry.getValue().getId(), userId);
        }
    }

    //确认
    private void updateResource(CloudServer server, CloudVendor vendor, Long userId) {
        // 更新资源表
        Resource resource = resourceRepository.query(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
                server.getId());
        List<String> ips = new ArrayList<>();
        if (!StringUtils.isEmpty(server.getPrivateIps()) && server.getPrivateIps().contains("[")) {
            ips.addAll(JSONArray.parseArray(server.getPrivateIps(), String.class));
        }
        if (!StringUtils.isEmpty(server.getPublicIps()) && server.getPublicIps().contains("[")) {
            ips.addAll(JSONArray.parseArray(server.getPublicIps(), String.class));
        }
        if (null != resource) {
            resource.setStatus(server.getStatus());
            resource.setPrivateIps(JSONObject.toJSONString(ips));
            resource.setMenderId(userId);
            resource.setAccurated(false);
            resource.setAuthed(false);
            resourceRepository.update(resource);
            server.setResource(resource);
        } else {
            resource = new Resource(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(), server.getId(),
                    null, server.getOsCategory(), vendor.getId());
            resource.preSave(server.getName(), server.getStatus(), userId, 0L, 0L);
            resource.setInventory(JSONObject.toJSONString(server));
            resource.setPrivateIps(JSONObject.toJSONString(ips));
            resource.setOwnerId(userId);
            resource.setAccurated(false);
            resource.setAuthed(false);
            resourceRepository.save(resource);
            server.setResource(resource);
        }
    }

    //确认
    private void updateSGroup(ServerModel serverModel, CloudServer cloudServer, Map<String, SecurityGroup> groupMap) throws Exception {
        serverSgroupRepository.removeBySid(cloudServer.getId());
        for (String groupUuid : serverModel.getSecurityGroups()) {
            SecurityGroup securityGroup = groupMap.get(groupUuid.toLowerCase());
            if (null != securityGroup) {
                ServerSgroup serverSgroup = new ServerSgroup(cloudServer.getId(), securityGroup.getId());
                serverSgroupRepository.save(serverSgroup);
            }
        }
    }

}