package com.bocloud.ims.service.transportor;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.entity.enums.ModuleCode;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.BackupModel;
import com.bocloud.cmp.model.ElasticIpModel;
import com.bocloud.cmp.model.FlavorModel;
import com.bocloud.cmp.model.HealthMonitorModel;
import com.bocloud.cmp.model.HuaweiSyncModel;
import com.bocloud.cmp.model.ImageModel;
import com.bocloud.cmp.model.KeypairModel;
import com.bocloud.cmp.model.LbListenerModel;
import com.bocloud.cmp.model.LbListenerPolicyModel;
import com.bocloud.cmp.model.LbListenerRuleModel;
import com.bocloud.cmp.model.LbMemberModel;
import com.bocloud.cmp.model.LbModel;
import com.bocloud.cmp.model.LbPoolModel;
import com.bocloud.cmp.model.NatGatewayDnatRuleModel;
import com.bocloud.cmp.model.NatGatewayModel;
import com.bocloud.cmp.model.NatGatewaySnatRuleModel;
import com.bocloud.cmp.model.PortFixedIpModel;
import com.bocloud.cmp.model.PortModel;
import com.bocloud.cmp.model.RegionModel;
import com.bocloud.cmp.model.SecurityGroupModel;
import com.bocloud.cmp.model.SecurityGroupRuleModel;
import com.bocloud.cmp.model.ServerModel;
import com.bocloud.cmp.model.ServerVolumeModel;
import com.bocloud.cmp.model.SnapshotModel;
import com.bocloud.cmp.model.SubnetModel;
import com.bocloud.cmp.model.TagModel;
import com.bocloud.cmp.model.VaultsModel;
import com.bocloud.cmp.model.VolumeModel;
import com.bocloud.cmp.model.VolumeTypeModel;
import com.bocloud.cmp.model.VpcModel;
import com.bocloud.cmp.model.ZoneModel;
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.VolumeType;
import com.bocloud.ims.entity.resource.Backup;
import com.bocloud.ims.entity.resource.BackupVaults;
import com.bocloud.ims.entity.resource.CloudServer;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.ElasticIp;
import com.bocloud.ims.entity.resource.Flavor;
import com.bocloud.ims.entity.resource.HealthMonitor;
import com.bocloud.ims.entity.resource.Image;
import com.bocloud.ims.entity.resource.IpPool;
import com.bocloud.ims.entity.resource.Keypair;
import com.bocloud.ims.entity.resource.LbListener;
import com.bocloud.ims.entity.resource.LbListenerPolicy;
import com.bocloud.ims.entity.resource.LbListenerRule;
import com.bocloud.ims.entity.resource.LbMember;
import com.bocloud.ims.entity.resource.LbPool;
import com.bocloud.ims.entity.resource.LoadBalancer;
import com.bocloud.ims.entity.resource.NatGateway;
import com.bocloud.ims.entity.resource.NatGatewayDnatRule;
import com.bocloud.ims.entity.resource.NatGatewaySnatRule;
import com.bocloud.ims.entity.resource.NatGatewaySnatRuleRelation;
import com.bocloud.ims.entity.resource.Port;
import com.bocloud.ims.entity.resource.PortFixedIp;
import com.bocloud.ims.entity.resource.Region;
import com.bocloud.ims.entity.resource.Resource;
import com.bocloud.ims.entity.resource.SecurityGroup;
import com.bocloud.ims.entity.resource.SecurityGroupRule;
import com.bocloud.ims.entity.resource.ServerSgroup;
import com.bocloud.ims.entity.resource.Snapshot;
import com.bocloud.ims.entity.resource.Subnet;
import com.bocloud.ims.entity.resource.Tag;
import com.bocloud.ims.entity.resource.Volume;
import com.bocloud.ims.entity.resource.VolumeTypeZone;
import com.bocloud.ims.entity.resource.Vpc;
import com.bocloud.ims.entity.resource.Zone;
import com.bocloud.ims.repository.NatGatewaySnatRuleRelationRepository;
import com.bocloud.ims.repository.resource.BackupRepository;
import com.bocloud.ims.repository.resource.BackupVaultsRepository;
import com.bocloud.ims.repository.resource.CloudServerRepository;
import com.bocloud.ims.repository.resource.ElasticIpRepository;
import com.bocloud.ims.repository.resource.FlavorRepository;
import com.bocloud.ims.repository.resource.HealthMonitorRepository;
import com.bocloud.ims.repository.resource.ImageRepository;
import com.bocloud.ims.repository.resource.IpPoolRepository;
import com.bocloud.ims.repository.resource.KeypairRepository;
import com.bocloud.ims.repository.resource.LbListenerPolicyRepository;
import com.bocloud.ims.repository.resource.LbListenerRepository;
import com.bocloud.ims.repository.resource.LbListenerRuleRepository;
import com.bocloud.ims.repository.resource.LbMemberRepository;
import com.bocloud.ims.repository.resource.LbPoolRepository;
import com.bocloud.ims.repository.resource.LoadBalancerRepository;
import com.bocloud.ims.repository.resource.NatGatewayDnatRuleRepository;
import com.bocloud.ims.repository.resource.NatGatewayRepository;
import com.bocloud.ims.repository.resource.NatGatewaySnatRuleRepository;
import com.bocloud.ims.repository.resource.PoolGroupRepository;
import com.bocloud.ims.repository.resource.PortFixedIpRepository;
import com.bocloud.ims.repository.resource.PortRepository;
import com.bocloud.ims.repository.resource.RegionRepository;
import com.bocloud.ims.repository.resource.ResourceRepository;
import com.bocloud.ims.repository.resource.SecurityGroupRepository;
import com.bocloud.ims.repository.resource.SecurityGroupRuleRepository;
import com.bocloud.ims.repository.resource.ServerLabelRepository;
import com.bocloud.ims.repository.resource.ServerSgroupRepository;
import com.bocloud.ims.repository.resource.SnapshotRepository;
import com.bocloud.ims.repository.resource.SubnetRepository;
import com.bocloud.ims.repository.resource.TagRepository;
import com.bocloud.ims.repository.resource.VolumeRepository;
import com.bocloud.ims.repository.resource.VolumeTypeRepository;
import com.bocloud.ims.repository.resource.VolumeTypeZoneRepository;
import com.bocloud.ims.repository.resource.VpcRepository;
import com.bocloud.ims.repository.resource.ZoneRepository;
import com.bocloud.ims.service.model.cmdb.CmdbInfo;
import com.bocloud.ims.service.model.cmdb.CmdbRelation;
import com.bocloud.ims.service.utils.CmdbInfoConvertor;
import com.bocloud.ims.service.utils.IPAddress;
import com.bocloud.ims.service.utils.ListUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * 华为云同步类
 *
 * @author wangyu
 * @version 4.1.0-SNAPSHOT
 * @since 2018/9/25
 */
@Component("huaweiTransportor")
public class HuaweiTransportor implements Transportor {

	private static Logger logger = LoggerFactory.getLogger(HuaweiTransportor.class);

	@Autowired
	private SnapshotRepository snapshotRepository;
	@Autowired
	private ImageRepository imageRepository;
	@Autowired
	private FlavorRepository flavorRepository;
	@Autowired
	private CloudServerRepository cloudServerRepository;
	@Autowired
	private SubnetRepository subnetRepository;
	@Autowired
	private RegionRepository regionRepository;
	@Autowired
	private VolumeRepository volumeRepository;
	@Autowired
	private VolumeTypeRepository volumeTypeRepository;
	@Autowired
	private VolumeTypeZoneRepository volumeTypeZoneRepository;
	@Autowired
	private ResourceRepository resourceRepository;
	@Autowired
	private SecurityGroupRepository securityGroupRepository;
	@Autowired
	private SecurityGroupRuleRepository securityGroupRuleRepository;
	@Autowired
	private ServerSgroupRepository serverSgroupRepository;
	@Autowired
	private KeypairRepository keypairRepository;
	@Autowired
	private PortRepository portRepository;
	@Autowired
	private PortFixedIpRepository portFixedIpRepository;
	@Autowired
	private ElasticIpRepository elasticIpRepository;
	@Autowired
	private IpPoolRepository ipPoolRepository;
	@Autowired
	private ServerLabelRepository serverLabelRepository;
	@Autowired
	private ZoneRepository zoneRepository;
	@Autowired
	private VpcRepository vpcRepository;
	@Autowired
	private NatGatewayRepository natGatewayRepository;
	@Autowired
	private NatGatewayDnatRuleRepository dnatRuleRepository;
	@Autowired
	private NatGatewaySnatRuleRepository snatRuleRepository;
	@Autowired
	private NatGatewaySnatRuleRelationRepository ruleRelationRepository;
	@Autowired
	private BackupVaultsRepository backupVaultsRepository;
	@Autowired
	private BackupRepository backupRepository;

	@Autowired
	private LoadBalancerRepository loadBalancerRepository;

	@Autowired
	private LbListenerRepository lbListenerRepository;

	@Autowired
	private LbPoolRepository lbPoolRepository;
	@Autowired
	private LbMemberRepository lbMemberRepository;
	@Autowired
	private HealthMonitorRepository healthMonitorRepository;

	@Autowired
	private LbListenerPolicyRepository lbListenerPolicyRepository;

	@Autowired
	private LbListenerRuleRepository lbListenerRuleRepository;

	@Autowired
	private TagRepository tagRepository;

	@Override
	public BocloudResult sync(CloudVendor vendor, Object data, Region region, Long userId, List<CmdbInfo> infos) {
		try {
			if (null != data) {
				if (cloudServerRepository.hasBuilding(vendor.getId())) {
					return new BocloudResult(false, "该平台下有虚拟机正在创建，请稍后进行同步操作");
				}
				Long vendorId = vendor.getId();
				String content = JSONObject.toJSONString(data);
				HuaweiSyncModel model = JSONObject.parseObject(content, HuaweiSyncModel.class);
				// 同步可用区域
				logger.info("Starting sync region......");
				this.syncRegions(model.getRegions(), vendor, userId, region.getRegionId());
				List<Zone> zoneList = zoneRepository.listByRegionId(region.getRegionId(), vendorId);
				Map<String, Long> zoneMap = new HashMap<>(8);
				for (Zone zone : zoneList) {
					zoneMap.put(zone.getZoneId(), zone.getId());
				}
				logger.info("End sync region......");

				// 同步vpc
				logger.info("Starting sync vpc......");
				this.syncVpc(model.getVpcModels(), vendor.getId(), userId, region.getRegionId());
				Map<String, Long> vpcMap = new HashMap<>(8);
				List<Vpc> vpcList = vpcRepository.list(vendorId, region.getRegionId());
				for (Vpc vpc : vpcList) {
					vpcMap.put(vpc.getVpcId(), vpc.getId());
				}
				Map<String, Long> subnetMap = new HashMap<>(8);
				Map<String, Subnet> neutronSubnetMap = new HashMap<>(8);
				List<Subnet> subnetList = subnetRepository.listByRegion(vendorId, region.getRegionId());
				for (Subnet subnet : subnetList) {
					subnetMap.put(subnet.getSubnetUuid(), subnet.getId());
					neutronSubnetMap.put(subnet.getNeutronSubnetUuid(), subnet);
				}
				logger.info("End sync vpc......");
				// 同步端口
				logger.info("Starting sync port......");
				this.syncPort(model.getPortModels(), region.getRegionId(), vendorId, userId);
				Map<String, Long> portMap = new HashMap<>(8);
				List<Port> ports = portRepository.listByVid(vendorId, region.getRegionId());
				for (Port port : ports) {
					portMap.put(port.getPortUuid(), port.getId());
				}
				logger.info("End sync port...");
				// 同步弹性IP
				logger.info("Starting sync elastic ip......");
				this.syncElasticIp(model.getElasticIpModels(), region.getRegionId(), vendorId, userId);
				Map<String, Long> elasticIpMap = new HashMap<>(8);
				List<ElasticIp> floatingIps = elasticIpRepository.listByVid(vendorId, region.getRegionId());
				for (ElasticIp elasticIp : floatingIps) {
					elasticIpMap.put(elasticIp.getElasticIpUuid(), elasticIp.getId());
				}
				logger.info("End sync elastic ip...");
				// 同步安全组
				logger.info("Starting sync security group......");
				this.syncSecurityGroup(model.getGroupModels(), vpcMap, vendorId, userId, region.getRegionId());
				logger.info("End sync security group......");
				// 同步虚拟机
				logger.info("Starting sync server......");
				Map<String, CloudServer> serverMap = new HashMap<>(8);
				this.syncServer(model.getServerModels(), vendor, userId, region, vendor.getType(), serverMap, infos);
				Map<String, CloudServer> sMap = new HashMap<>(8);
				List<CloudServer> serverByVid = cloudServerRepository.listByVid(vendor.getId(), region.getRegionId());
				for (CloudServer cloudServer : serverByVid) {
					sMap.put(cloudServer.getInstanceId(), cloudServer);
				}
				logger.info("End sync server......");
				// 同步镜像
				Map<String, Image> imageMap = Maps.newHashMap();
				logger.info("Starting sync image......");
				this.syncImage(model.getImageModels(), vendorId, region.getRegionId(), userId, vendor.getType(),
						imageMap);
				logger.info("End sync image......");
				// 同步云硬盘类型
				logger.info("Starting sync volume type......");
				this.syncVolumeType(model.getVolumeTypeModels(), vendorId, region.getRegionId(), userId, zoneMap);
				logger.info("End sync volume type......");
				// 同步云硬盘
				logger.info("Starting sync volume......");
				this.syncVolume(model.getVolumeModels(), vendorId, region.getRegionId(), userId, sMap);
				logger.info("End sync volume......");
				// 获取云硬盘信息
				Map<String, Volume> volumeMap = Maps.newHashMap();
				List<Volume> volumes = volumeRepository.listByVendorId(vendorId);
				for (Volume volume : volumes) {
					volumeMap.put(volume.getVolumeUuid(), volume);
				}
				// 同步快照
				logger.info("Starting sync snapshot......");
				this.syncSnapshot(model.getSnapshotModels(), vendorId, userId, region.getRegionId(), volumeMap);
				logger.info("End sync snapshot......");
				// 同步规格
				logger.info("Starting sync flavor......");
				this.syncFlavor(model.getFlavorModels(), vendorId, userId, region.getRegionId());
				logger.info("End sync flavor......");
				// 同步密钥
				logger.info("Starting sync keypair......");
				this.syncKeypair(model.getKeypairModels(), region.getRegionId(), vendorId, userId);
				logger.info("End sync keypair...");

				// 同步nat网关
				logger.info("Starting sync nat gateway......");
				this.syncNatGateway(model.getNatGatewayModels(), region.getRegionId(), vendorId, userId, vpcMap,
						subnetMap);
				Map<String, Long> natGatewayMap = new HashMap<>(8);
				List<NatGateway> natGateways = natGatewayRepository.listByVendorId(vendorId, region.getRegionId());
				for (NatGateway natGateway : natGateways) {
					natGatewayMap.put(natGateway.getUuid(), natGateway.getId());
				}
				logger.info("End sync nat gateway......");

				// 同步nat网关dnat规则
				logger.info("Starting sync nat gateway dnat......");
				this.syncNatGatewayDnatRule(model.getDnatRuleModels(), region.getRegionId(), vendorId, userId,
						natGatewayMap, elasticIpMap, portMap);
				logger.info("End sync nat gateway dnat......");

				// 同步nat网关snat规则
				logger.info("Starting sync nat gateway snat......");
				this.syncNatGatewaySnatRule(model.getSnatRuleModels(), region.getRegionId(), vendorId, userId,
						natGatewayMap, elasticIpMap, subnetMap);
				logger.info("End sync nat gateway snat......");

				// 同步负载均衡
				logger.info("Starting sync lb......");
				this.syncLoadBalancer(model.getLbModels(), vpcMap, neutronSubnetMap, vendor.getId(), userId,
						region.getRegionId());
				List<LoadBalancer> balancers = loadBalancerRepository.listByVid(vendor.getId(), region.getRegionId());
				Map<String, Long> balancerMap = Maps.newHashMap();
				for (LoadBalancer balancer : balancers) {
					balancerMap.put(balancer.getLbUuid(), balancer.getId());
				}
				logger.info("End sync lb......");

				// 同步侦听器
				logger.info("Starting sync listener......");
				this.syncLbListener(model.getLbListenerModels(), balancerMap, vendor.getId(), userId,
						region.getRegionId());
				List<LbListener> lbListeners = lbListenerRepository.listByVid(vendor.getId(), region.getRegionId());
				Map<String, Long> listenerMap = Maps.newHashMap();

				for (LbListener listener : lbListeners) {
					listenerMap.put(listener.getListenerUuid(), listener.getId());
				}
				logger.info("End sync lb listener......");

				// 后端云服务器组
				logger.info("Starting sync lb pool......");
				this.syncLbPool(model.getLbPoolModels(), listenerMap, balancerMap, vendor.getId(), userId,
						region.getRegionId());
				List<LbPool> targetGroups = lbPoolRepository.listByVid(vendor.getId(), region.getRegionId());
				Map<String, Long> tgMap = Maps.newHashMap();

				Map<String, LbPool> lbPoolMap = Maps.newHashMap();
				for (LbPool group : targetGroups) {
					tgMap.put(group.getPoolUuid(), group.getId());
					lbPoolMap.put(group.getPoolUuid(), group);
				}
				logger.info("End sync lb pool......");
				// 后端云服务器
				logger.info("Starting sync lb member......");
				this.syncLbMember(model.getLbMemberModels(), lbPoolMap, neutronSubnetMap, vendor.getId(), userId,
						region.getRegionId());
				logger.info("End sync lb member......");

				// 健康检查
				logger.info("Starting sync Health Monitor......");
				this.syncHealthMonitor(model.getHealthMonitorModels(), lbPoolMap, vendor.getId(), userId,
						region.getRegionId());
				logger.info("End sync Health Monitor......");

				// 转发策略
				logger.info("Starting sync Listener Policy......");
				this.syncL7policy(model.getLbL7PolicyModels(), tgMap, listenerMap, vendor.getId(), userId,
						region.getRegionId());
				logger.info("End sync Listener Policy......");

				List<LbListenerPolicy> lbL7PolicyList = lbListenerPolicyRepository.listByVid(vendor.getId(),
						region.getRegionId());
				Map<String, Long> l7PolicyMap = Maps.newHashMap();

				for (LbListenerPolicy group : lbL7PolicyList) {
					l7PolicyMap.put(group.getPolicyUuid(), group.getId());
				}
				// 转发规则
				logger.info("Starting sync Listener Rule......");
				this.syncL7rule(model.getLbL7RuleModels(), l7PolicyMap, vendor.getId(), userId, region.getRegionId());
				logger.info("End sync Listener Rule......");

				// 同步华为存储库
				logger.info("statr sync Vaults...");
				this.syncBackupVaults(model.getVaultsModels(), vendor.getId(), userId, region.getRegionId(), volumeMap,
						sMap);
				logger.info("statr sync Vaults... END");

				// 同步华为存储resource
				logger.info("statr sync Backup...");
				this.syncBackupResources(model.getBackupModels(), vendor.getId(), userId, region.getRegionId());
				logger.info("statr sync Backup... END");

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

	private void syncBackupVaults(List<VaultsModel> vaultsModels, Long vendorId, Long userId, String regionId,
			Map<String, Volume> volumeMap, Map<String, CloudServer> sMap) {
		// 当浮动IP为空时，清空数据库
		if (ListTool.isEmpty(vaultsModels)) {
			backupVaultsRepository.deleteByVendorId(vendorId, regionId, userId);
			return;
		}
		List<BackupVaults> backupVaultsList = backupVaultsRepository.list(vendorId, regionId);
		Map<String, BackupVaults> vaultsMap = Maps.newHashMap();
		for (BackupVaults backupVaults : backupVaultsList) {
			vaultsMap.put(backupVaults.getVaultsUuid(), backupVaults);
		}
		BackupVaults backupVaults = null;
		for (VaultsModel model : vaultsModels) {
			String vaultsUuid = model.getVaultsUuid();
			if (vaultsMap.containsKey(vaultsUuid)) {
				backupVaults = vaultsMap.get(vaultsUuid);
				BeanUtils.copyProperties(model, backupVaults);
				backupVaults.setMenderId(userId);
				backupVaults.setRegionId(regionId);
				backupVaults.setGmtModify(new Date());
				backupVaults.setCreatorId(userId);
				backupVaults.setVendorId(vendorId);
				backupVaultsRepository.update(backupVaults);
				syncResourceRelation(vendorId, model, volumeMap, sMap);
				vaultsMap.remove(vaultsUuid);
				continue;
			}
			backupVaults = new BackupVaults();
			BeanUtils.copyProperties(model, backupVaults);
			backupVaults.setMenderId(userId);
			backupVaults.setRegionId(regionId);
			backupVaults.setGmtModify(new Date());
			backupVaults.setTenantId(0L);
			backupVaults.setProjectId(0L);
			backupVaults.setCreatorId(userId);
			backupVaults.setVendorId(vendorId);
			backupVaultsRepository.save(backupVaults);
			syncResourceRelation(vendorId, model, volumeMap, sMap);
		}
		for (Map.Entry<String, BackupVaults> entry : vaultsMap.entrySet()) {
			backupVaultsRepository.delete(entry.getValue().getId(), userId);
		}

	}

	private void syncResourceRelation(Long vendorId, VaultsModel model, Map<String, Volume> volumeMap,
			Map<String, CloudServer> serverMap) {
		String objectType = model.getObjectType();
		switch (objectType) {
		case "disk":
			List<VolumeModel> volumeModels = model.getVolumeModels();
			if (ListTool.isEmpty(volumeModels)) {
				return;
			}
			for (VolumeModel volumeModel : volumeModels) {
				String volumeUuid = volumeModel.getVolumeUuid();
				if (volumeMap.containsKey(volumeUuid)) {
					Volume volume = volumeMap.get(volumeUuid);
					volume.setVaultsUuid(model.getVaultsUuid());
					volume.setBackupCount(volumeModel.getBackupCount());
					volumeRepository.update(volume);
				}
			}
			break;
		case "server":
			List<ServerModel> serverModels = model.getServerModels();
			if (ListTool.isEmpty(serverModels)) {
				return;
			}
			for (ServerModel serverModel : serverModels) {
				String instanceId = serverModel.getInstanceId();
				if (serverMap.containsKey(instanceId)) {
					CloudServer cloudServer = serverMap.get(instanceId);
					cloudServer.setVaultsUuid(model.getVaultsUuid());
					cloudServer.setBackupCount(serverModel.getBackupCount());
					cloudServerRepository.update(cloudServer);
				}
			}
			break;
		default:
			break;
		}
	}

	private void syncBackupResources(List<BackupModel> backupModels, Long vendorId, Long userId, String regionId) {
		if (ListTool.isEmpty(backupModels)) {
			backupRepository.deleteByVendorId(vendorId, regionId, userId);
			return;
		}
		List<Backup> backupList = backupRepository.list(vendorId, regionId);
		Map<String, Backup> backupMap = Maps.newHashMap();
		for (Backup backup : backupList) {
			if (backupMap.containsKey(backup.getBackupUuid())) {
				backupRepository.delete(backup.getId(), userId);
			} else {
				backupMap.put(backup.getBackupUuid(), backup);
			}
		}
		Backup backup = null;
		for (BackupModel model : backupModels) {
			String backupUuid = model.getBackupUuid();
			if (backupMap.containsKey(backupUuid)) {
				backup = backupMap.get(backupUuid);
				BeanUtils.copyProperties(model, backup);
				backup.setMenderId(userId);
				backup.setRegionId(regionId);
				backup.setGmtModify(new Date());
				backup.setCreatorId(userId);
				backup.setVendorId(vendorId);
				backupRepository.update(backup);
				backupMap.remove(backupUuid);
				continue;
			}
			backup = new Backup();
			BeanUtils.copyProperties(model, backup);
			backup.setMenderId(userId);
			backup.setRegionId(regionId);
			backup.setGmtModify(new Date());
			backup.setTenantId(0L);
			backup.setProjectId(0L);
			backup.setCreatorId(userId);
			backup.setVendorId(vendorId);
			backupRepository.save(backup);
		}
		for (Map.Entry<String, Backup> entry : backupMap.entrySet()) {
			backupRepository.delete(entry.getValue().getId(), userId);
		}

	}

	private void syncSubnet(List<SubnetModel> models, Long vendorId, Long userId, String region, String vpcId,
			Map<String, Vpc> vpcMap) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			subnetRepository.deleteByVpcId(vendorId, vpcId, userId);
			return;
		}
		List<Subnet> subnetList = subnetRepository.listByVpcId(vendorId, vpcId);
		Map<String, Subnet> subnetMap = Maps.newHashMap();
		for (Subnet subnet : subnetList) {
			subnetMap.put(subnet.getSubnetUuid(), subnet);
		}
		for (SubnetModel model : models) {
			Subnet subnet = new Subnet();
			if (subnetMap.containsKey(model.getSubnetUuid())) {
				subnet = subnetMap.get(model.getSubnetUuid());
				BeanUtils.copyProperties(model, subnet);
				subnet.setMenderId(userId);
				subnet.setRegionId(region);
				Optional.ofNullable(vpcMap.get(vpcId)).map(Vpc::getId).ifPresent(subnet::setVpcId);
				subnetRepository.update(subnet);
				subnetMap.remove(model.getSubnetUuid());
				continue;
			}
			BeanUtils.copyProperties(model, subnet);
			subnet.setMenderId(userId);
			subnet.setGmtModify(new Date());
			subnet.setCreatorId(userId);
			subnet.setVendorId(vendorId);
			subnet.setRegionId(region);
			Optional.ofNullable(vpcMap.get(vpcId)).map(Vpc::getId).ifPresent(subnet::setVpcId);
			subnetRepository.save(subnet);
			subnetMap.remove(model.getSubnetUuid());
		}
		for (Entry<String, Subnet> entry : subnetMap.entrySet()) {
			subnetRepository.remove(entry.getValue().getId(), userId);
		}
	}

	private void syncVpc(List<VpcModel> models, Long vendorId, Long userId, String region) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			vpcRepository.deleteByVid(vendorId, region, userId);
			return;
		}
		List<Vpc> vpcs = vpcRepository.list(vendorId, region);
		Map<String, Vpc> vpcMap = Maps.newHashMap();
		for (Vpc vpc : vpcs) {
			vpcMap.put(vpc.getVpcId(), vpc);
		}
		for (VpcModel model : models) {
			Vpc vpc = new Vpc();
			if (vpcMap.containsKey(model.getVpcId())) {
				vpc = vpcMap.get(model.getVpcId());
				BeanUtils.copyProperties(model, vpc);
				vpc.setRegionId(region);
				vpcRepository.update(vpc);
				// 同步子网
				this.syncSubnet(model.getSubnetModels(), vendorId, userId, region, vpc.getVpcId(), vpcMap);
				vpcMap.remove(model.getVpcId());
				continue;
			}
			BeanUtils.copyProperties(model, vpc);
			vpc.setCreatorId(userId);
			vpc.setVendorId(vendorId);
			vpc.setMenderId(userId);
			vpc.setRegionId(region);
			vpc.setTenantId(0L);
			vpc.setProjectId(0L);
			vpcRepository.save(vpc);
			// 同步子网
			this.syncSubnet(model.getSubnetModels(), vendorId, userId, region, vpc.getVpcId(), vpcMap);
			vpcMap.remove(model.getVpcId());
		}
		for (Entry<String, Vpc> entry : vpcMap.entrySet()) {
			vpcRepository.delete(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步安全组和规则
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncSecurityGroup(List<SecurityGroupModel> models, Map<String, Long> vpcMap, Long vendorId,
			Long userId, String region) throws Exception {
		// 当安全组为空时,删除数据库残留数据
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			securityGroupRepository.removeByVid(vendorId, region, userId);
			return;
		}
		List<SecurityGroup> groups = securityGroupRepository.listByVendorId(vendorId, region);
		Map<String, SecurityGroup> groupMap = Maps.newHashMap();
		for (SecurityGroup group : groups) {
			groupMap.put(group.getGroupUuid(), group);
		}
		for (SecurityGroupModel model : models) {
			SecurityGroup group = new SecurityGroup();
			if (groupMap.containsKey(model.getGroupUuid())) {
				group = groupMap.get(model.getGroupUuid());
				BeanUtils.copyProperties(model, group);
				group.setVpcId(vpcMap.get(group.getVpcUuid()));
				group.setMenderId(userId);
				securityGroupRepository.update(group);
				securityGroupRuleRepository.removeBySgId(group.getId(), userId);
				for (SecurityGroupRuleModel securityGroupRuleModel : model.getModels()) {
					SecurityGroupRule securityGroupRule = new SecurityGroupRule();
					BeanUtils.copyProperties(securityGroupRuleModel, securityGroupRule);
					securityGroupRule.setCreatorId(userId);
					securityGroupRule.setVendorId(vendorId);
					securityGroupRule.setGroupId(group.getId());
					securityGroupRule.setGroupUuid(group.getGroupUuid());
					securityGroupRuleRepository.save(securityGroupRule);
				}
				groupMap.remove(model.getGroupUuid());
				continue;
			}
			group = JSONObject.parseObject(JSONObject.toJSONString(model), SecurityGroup.class);
			group.setVpcId(vpcMap.get(group.getVpcUuid()));
			group.preSave(userId, userId, vendorId, 0L, 0L);
			securityGroupRepository.save(group);
			for (SecurityGroupRuleModel securityGroupRuleModel : model.getModels()) {
				SecurityGroupRule securityGroupRule = new SecurityGroupRule();
				BeanUtils.copyProperties(securityGroupRuleModel, securityGroupRule);
				securityGroupRule.setCreatorId(userId);
				securityGroupRule.setVendorId(vendorId);
				securityGroupRule.setGroupId(group.getId());
				securityGroupRule.setGroupUuid(group.getGroupUuid());
				securityGroupRuleRepository.save(securityGroupRule);
			}
		}
		// 删除不存在的安全组
		for (Entry<String, SecurityGroup> entry : groupMap.entrySet()) {
			securityGroupRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步所属域
	 *
	 * @param userId
	 * @throws Exception
	 */
	private void syncRegions(List<RegionModel> regionModels, CloudVendor vendor, Long userId, String regionId)
			throws Exception {
		if (regionModels == null) {
			return;
		}
		if (regionModels.isEmpty()) {
			regionRepository.deleteByVid(vendor.getId(), regionId);
			zoneRepository.deleteByRegionId(regionId, vendor.getId());
			return;
		}
		for (RegionModel model : regionModels) {
			// 同步区
			syncZone(model.getZones(), model.getCode(), vendor, userId);
		}
	}

	private void syncZone(List<ZoneModel> models, String regionId, CloudVendor vendor, Long userId) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			zoneRepository.deleteByRegionId(regionId, vendor.getId());
			return;
		}
		List<Zone> zones = zoneRepository.listByRegionId(regionId, vendor.getId());
		Map<String, Zone> zoneMap = Maps.newHashMap();
		for (Zone zone : zones) {
			zoneMap.put(zone.getZoneId(), zone);
		}
		Zone zone = null;
		for (ZoneModel model : models) {
			zone = new Zone();
			if (zoneMap.containsKey(model.getZoneId())) {
				zone = zoneMap.get(model.getZoneId());
				BeanUtils.copyProperties(model, zone);
				zone.setVendorId(vendor.getId());
				zone.setRegionId(regionId);
				zoneRepository.update(zone);
				zoneMap.remove(model.getZoneId());
				continue;
			}
			BeanUtils.copyProperties(model, zone);
			zone.setVendorId(vendor.getId());
			zone.setRegionId(regionId);
			zoneRepository.save(zone);
			zoneMap.remove(model.getZoneId());
		}
		for (Map.Entry<String, Zone> entry : zoneMap.entrySet()) {
			zoneRepository.delete(entry.getValue().getId());
		}

	}

	/**
	 * 同步虚拟机
	 *
	 * @param serverModels
	 * @param vendor
	 * @param userId
	 * @param region
	 * @param type
	 * @param serverMap
	 * @param infos
	 * @param infos
	 * @throws Exception
	 */
	private void syncServer(List<ServerModel> serverModels, CloudVendor vendor, Long userId, Region region, String type,
			Map<String, CloudServer> serverMap, List<CmdbInfo> infos) throws Exception {
		if (serverModels == null) {
			return;
		}
		if (serverModels.isEmpty()) {
			List<CloudServer> servers = cloudServerRepository.listByVendorId(vendor.getId(), region.getRegionId());
			for (CloudServer server : servers) {
				serverSgroupRepository.removeBySid(server.getId());
				volumeRepository.detachVolumes(server.getId(), userId);
				serverLabelRepository.deleteByTarget(server.getId(), "VM");
				// cmdb：删除虚机
				infos.add(CmdbInfoConvertor.getInfo(server, "delete", null));
			}
			cloudServerRepository.removeByVid(vendor.getId(), region.getRegionId(), userId);
			// 删除资源表
			resourceRepository.removeByVidReg(vendor.getId(), region.getRegionId(), userId);
			return;
		}
		// 获取平台虚拟机信息
		List<CloudServer> servers = cloudServerRepository.listByVendorId(vendor.getId(), region.getRegionId());
		Map<String, CloudServer> cloudSeverMap = Maps.newHashMap();
		for (CloudServer server : servers) {
			cloudSeverMap.put(server.getInstanceId(), server);
		}
		// 获取平台安全组信息
		List<SecurityGroup> securityGroups = securityGroupRepository.listByVendorId(vendor.getId(),
				region.getRegionId());
		Map<String, Long> groupMap = Maps.newHashMap();
		for (SecurityGroup group : securityGroups) {
			groupMap.put(group.getName(), group.getId());
		}
		CloudServer vm = null;
		for (ServerModel server : serverModels) {
			List<CmdbRelation> relations = new ArrayList<>();
			relations.add(new CmdbRelation(ModuleCode.REGION.name(), 1L, ListUtils.getList(region.getGuid())));
			Flavor flavor = flavorRepository.getByFlavorUuid(server.getFlavorUuid());
			// 更新已创建的虚拟机
			if (cloudSeverMap.containsKey(server.getInstanceId())) {
				vm = cloudSeverMap.get(server.getInstanceId());

				String account = vm.getAccount();
				if (StringUtils.hasText(account)) {
					Image image = imageRepository.getByImageUuid(server.getImageUuid());
					if (null != image) {
						account = image.getDefaultUser();
					}
				}
				server.setAccount(account);
				server.setPassword(vm.getPassword());
				BeanUtils.copyProperties(server, vm);

				vm.setOsCategory(server.getOsCategory());
				vm.setOsName(server.getOsName());
				vm.setOsVersion(server.getOsVersion());
				if ("error".equalsIgnoreCase(server.getStatus())) {
					vm.setStatus(BocloudStatus.Server.EXCEPTION.name());
				} else {
					vm.setStatus(server.getStatus());
				}

				List<Long> sgIds = null;
				String groups = server.getGroups();
				if (!StringUtils.hasText(groups)) {
					List<String> groupList = JSONArray.parseArray(groups, String.class);
					if (null != groupList && groupList.size() > 0) {
						sgIds = new ArrayList<Long>();
						for (String sgName : groupList) {
							sgIds.add(groupMap.get(sgName));
						}
					}
				}

				vm.setHostId(0L);
				vm.setPassword(server.getPassword());
				vm.setIsTemplate(false);
				vm.setGmtVmCreate(server.getGmtVmCreate());
				vm.setPrivateIps(server.getPrivateIps());
				if (null != flavor) {
					vm.setCpu(flavor.getCpu());
					vm.setMemory(flavor.getMemory());
				}
				vm.setRegionId(region.getRegionId());
				vm.setVendorId(vendor.getId());
				cloudServerRepository.update(vm);
				// CMDB更新集群数据
				infos.add(CmdbInfoConvertor.getInfo(vm, null, relations));
				// 更新资源表
				updateResource(vm, vendor, region.getRegionId(), userId);
				cloudSeverMap.remove(vm.getInstanceId());
				// 更新虚拟机绑定的安全组
				serverSgroupRepository.removeBySid(vm.getId());
				updateSGroup(vm.getId(), JSON.toJSONString(server.getSecurityGroups()), groupMap);
				serverMap.remove(vm.getInstanceId());
				syncTag(server.getTagModels(), vendor.getId(), userId, region.getRegionId(), vm.getInstanceId());
				continue;
			}
			vm = new CloudServer();
			BeanUtils.copyProperties(server, vm);
			if ("error".equalsIgnoreCase(server.getStatus())) {
				vm.setStatus(BocloudStatus.Server.EXCEPTION.name());
			} else {
				vm.setStatus(server.getStatus());
			}
			vm.setVendorId(vendor.getId());
			vm.setRegionId(region.getRegionId());
			vm.setIsTemplate(false);
			vm.setResourceId(IDFactory.instance().uuid());
			vm.setVendorType(type);
			vm.setGmtVmCreate(server.getGmtVmCreate());
			vm.setPrivateIps(server.getPrivateIps());
			vm.setMenderId(0L);
			vm.setOwnerId(0L);
			vm.setTenantId(0L);
			vm.setProjectId(0L);

			List<Long> sgIds = null;
			String groups = server.getGroups();
			if (!StringUtils.hasText(groups)) {
				List<String> groupList = JSONArray.parseArray(groups, String.class);
				if (null != groupList && groupList.size() > 0) {
					sgIds = new ArrayList<Long>();
					for (String sgName : groupList) {
						sgIds.add(groupMap.get(sgName));
					}
				}
			}
			vm.setRecycle(false);
			vm.preSave(userId, userId, vendor.getId(), 0L, null, null, 0L, 0L);
			if (StringUtils.hasText(vm.getOsCategory())) {
				vm.setOsCategory(OSCategory.LINUX.name());
			}
			String account = vm.getAccount();
			if (StringUtils.hasText(account)) {
				Image image = imageRepository.getByImageUuid(vm.getImageUuid());
				if (null != image) {
					account = image.getDefaultUser();
				}
			}
			server.setAccount(account);
			if (null != flavor) {
				vm.setCpu(flavor.getCpu());
				vm.setMemory(flavor.getMemory());
			}
			cloudServerRepository.save(vm);
			// CMDB更新集群数据
			infos.add(CmdbInfoConvertor.getInfo(vm, null, relations));
			// 更新资源表
			updateResource(vm, vendor, region.getRegionId(), userId);
			serverSgroupRepository.removeBySid(vm.getId());
			updateSGroup(vm.getId(), JSON.toJSONString(server.getSecurityGroups()), groupMap);

			syncTag(server.getTagModels(), vendor.getId(), userId, region.getRegionId(), vm.getInstanceId());
		}
		for (Map.Entry<String, CloudServer> entry : cloudSeverMap.entrySet()) {
			CloudServer server = entry.getValue();
			resourceRepository.remove(server.getId(), ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
					userId);
			// cmdb：删除虚拟机
			infos.add(CmdbInfoConvertor.getInfo(entry.getValue(), "delete", null));
			volumeRepository.detachVolumes(server.getId(), userId);
			serverSgroupRepository.removeBySid(server.getId());
			cloudServerRepository.remove(server.getId(), userId);
			serverLabelRepository.deleteByTarget(server.getId(), "VM");
		}
	}

	/**
	 * 更新资源表相关信息
	 *
	 * @param server
	 * @param vendor
	 * @param userId
	 * @throws Exception
	 */
	private void updateResource(CloudServer server, CloudVendor vendor, String region, Long userId) throws Exception {
		// 更新资源表
		Resource resource = resourceRepository.query(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
				server.getId());
		// 保存资源
		List<String> ips = Lists.newArrayList();
		if (!StringUtils.hasText(server.getPrivateIps())) {
			List<JSONObject> objects = JSONObject.parseArray(server.getPrivateIps(), JSONObject.class);
			for (JSONObject object : objects) {
				ips.add(object.getString("address"));
			}
		}
		if (null != resource) {
			resource.setStatus(server.getStatus());
			resource.setPrivateIps(JSONObject.toJSONString(ips));
			resource.setRegionId(region);
			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.setRegionId(region);
			resource.setPrivateIps(JSONObject.toJSONString(ips));
			resource.setOwnerId(userId);
			resource.setAccurated(false);
			resource.setAuthed(false);
			resourceRepository.save(resource);
			server.setResource(resource);
		}
	}

	private void updateSGroup(Long serverId, String groups, Map<String, Long> groupMap) throws Exception {
		if (!StringUtils.hasText(groups)) {
			return;
		}
		List<String> groupList = JSONArray.parseArray(groups, String.class);
		if (ListTool.isEmpty(groupList)) {
			return;
		}
		for (String group : groupList) {
			if ("default".equals(group)) {
				group = "Sys-" + group;
			}
			Long groupId = groupMap.get(group);
			ServerSgroup serverSgroupInfo = serverSgroupRepository.getByServerGroup(serverId, groupId);
			if (null == serverSgroupInfo) {
				ServerSgroup serverSgroup = new ServerSgroup(serverId, groupMap.get(group));
				serverSgroupRepository.save(serverSgroup);
			}
		}
	}

	/**
	 * 同步云硬盘快照
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @param regionId
	 * @param volumeMap
	 * @throws Exception
	 */
	private void syncSnapshot(List<SnapshotModel> models, Long vendorId, Long userId, String regionId,
			Map<String, Volume> volumeMap) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			snapshotRepository.removeByVid(vendorId, regionId, userId);
			return;
		}
		List<Snapshot> snapshots = snapshotRepository.listByVid(vendorId, regionId);
		Map<String, Snapshot> snapshotMap = Maps.newHashMap();
		for (Snapshot snapshot : snapshots) {
			snapshotMap.put(snapshot.getSnapshotUuid(), snapshot);
		}
		Region region = regionRepository.getByRegionId(regionId, vendorId);
		for (SnapshotModel model : models) {
			if (snapshotMap.containsKey(model.getSnapshotUuid())) {
				Snapshot snapshot = snapshotMap.get(model.getSnapshotUuid());
				BeanUtils.copyProperties(model, snapshot);
				snapshot.setRegionId(regionId);
				snapshot.setMenderId(userId);
				if (null != region) {
					snapshot.setRegion(region.getId());
				}
				Volume volume = volumeMap.get(model.getVolumeUuid());
				if (null != volume) {
					snapshot.setVolumeId(volume.getId());
					snapshot.setZone(volume.getZone());
				}
				snapshotRepository.update(snapshot);
				snapshotMap.remove(model.getSnapshotUuid());
			} else {
				Snapshot snapshot = JSONObject.parseObject(JSONObject.toJSONString(model), Snapshot.class);
				snapshot.setRegionId(regionId);
				if (null != region) {
					snapshot.setRegion(region.getId());
				}
				Volume volume = volumeMap.get(model.getVolumeUuid());
				if (null != volume) {
					snapshot.setVolumeId(volume.getId());
					snapshot.setZone(volume.getZone());
				}
				snapshot.preSave(userId, userId, vendorId, null, 0L, 0L);
				snapshotRepository.save(snapshot);
			}
		}
		for (Map.Entry<String, Snapshot> entry : snapshotMap.entrySet()) {
			snapshotRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步云硬盘
	 *
	 * @param volumeModels
	 * @param vendorId
	 * @param regionId
	 * @param userId
	 * @param serverMap
	 * @throws Exception
	 */
	private void syncVolume(List<VolumeModel> volumeModels, Long vendorId, String regionId, Long userId,
			Map<String, CloudServer> serverMap) throws Exception {
		if (volumeModels == null) {
			return;
		}
		if (volumeModels.isEmpty()) {
			volumeRepository.removeByVid(vendorId, regionId, userId);
			return;
		}
		List<Volume> volumes = volumeRepository.listByVendorId(vendorId, regionId);
		Map<String, Volume> volumeMap = Maps.newHashMap();
		for (Volume volume : volumes) {
			volumeMap.put(volume.getVolumeUuid(), volume);
		}
		Volume volume = null;
		for (VolumeModel volumeModel : volumeModels) {
			if (volumeMap.containsKey(volumeModel.getVolumeUuid())) {
				volume = volumeMap.get(volumeModel.getVolumeUuid());
				BeanUtils.copyProperties(volumeModel, volume);
				volume.setRegionId(regionId);
				volume.setVendorId(vendorId);
				volume.setStatus(volumeModel.getStatus().toUpperCase());
				volume.setCreateTime(volumeModel.getCreateTime());
				List<ServerVolumeModel> models = volumeModel.getModels();
				if (null != models && models.size() > 0) {
					ServerVolumeModel serverVolumeModel = models.get(0);
					volume.setDevice(serverVolumeModel.getDevice());
					volume.setInstanceId(serverVolumeModel.getInstanceId());
					CloudServer cloudServer = serverMap.get(serverVolumeModel.getInstanceId());
					if(null != cloudServer) {
						volume.setServerId(cloudServer.getId());
					}
				}
				volumeRepository.update(volume);
				volumeMap.remove(volumeModel.getVolumeUuid());
				syncTag(volumeModel.getTagModels(), vendorId, userId, regionId, volumeModel.getVolumeUuid());
				continue;
			}
			volume = new Volume();
			BeanUtils.copyProperties(volumeModel, volume);
			volume.setMenderId(0L);
			volume.setOwnerId(0L);
			volume.setRegionId(regionId);
			volume.setVendorId(vendorId);
			volume.setProjectId(0L);
			volume.setTenantId(0L);
			volume.setCreatorId(0L);
			volume.setStatus(volumeModel.getStatus().toUpperCase());
			volume.setCreateTime(volumeModel.getCreateTime());
			List<ServerVolumeModel> models = volumeModel.getModels();
			if (null != models && models.size() > 0) {
				ServerVolumeModel serverVolumeModel = models.get(0);
				volume.setDevice(serverVolumeModel.getDevice());
				volume.setInstanceId(serverVolumeModel.getInstanceId());
				CloudServer cloudServer = serverMap.get(serverVolumeModel.getInstanceId());
				if(null != cloudServer) {
					volume.setServerId(cloudServer.getId());
				}
			}
			volumeRepository.save(volume);

			syncTag(volumeModel.getTagModels(), vendorId, userId, regionId, volumeModel.getVolumeUuid());
		}
		// 删除异常数据
		for (Map.Entry<String, Volume> entry : volumeMap.entrySet()) {
			volumeRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步云硬盘类型
	 *
	 * @param typeModels
	 * @param vendorId
	 * @param regionId
	 * @param userId
	 * @param zoneMap
	 * @throws Exception
	 */
	private void syncVolumeType(List<VolumeTypeModel> typeModels, Long vendorId, String regionId, Long userId,
			Map<String, Long> zoneMap) throws Exception {
		if (typeModels == null) {
			return;
		}
		if (typeModels.isEmpty()) {
			volumeTypeRepository.deleteByVendorId(vendorId, regionId);
			return;
		}
		List<VolumeType> volumeTypes = volumeTypeRepository.listByVendorId(vendorId, regionId);
		Map<String, VolumeType> volumeTypeMap = Maps.newHashMap();
		for (VolumeType type : volumeTypes) {
			volumeTypeMap.put(type.getVolumeTypeUuid(), type);
		}
		VolumeType volumeType = null;
		for (VolumeTypeModel typeModel : typeModels) {
			if (volumeTypeMap.containsKey(typeModel.getVolumeTypeUuid())) {
				volumeType = volumeTypeMap.get(typeModel.getVolumeTypeUuid());
				BeanUtils.copyProperties(typeModel, volumeType);
				volumeType.setRegionId(regionId);
				volumeType.setVendorId(vendorId);
				volumeType.setVolumeType(typeModel.getName());
				volumeTypeRepository.update(volumeType);
				volumeTypeMap.remove(typeModel.getVolumeTypeUuid());
				continue;
			}
			volumeType = new VolumeType();
			BeanUtils.copyProperties(typeModel, volumeType);
			volumeType.setRegionId(regionId);
			volumeType.setVendorId(vendorId);
			volumeType.setVolumeType(typeModel.getName());
			volumeTypeRepository.save(volumeType);
			volumeTypeMap.remove(typeModel.getVolumeTypeUuid());
			this.syncVolumeTypeZone(typeModel.getZones(), typeModel.getSoldOutZones(), volumeType.getId(), zoneMap);
		}
		// 删除异常数据
		for (Map.Entry<String, VolumeType> entry : volumeTypeMap.entrySet()) {
			volumeTypeRepository.remove(entry.getValue().getId());
			volumeTypeZoneRepository.removeByVolumeTypeId(entry.getValue().getId());
		}
	}

	private void syncVolumeTypeZone(List<String> zones, List<String> soldOutZones, Long volumeTypeId,
			Map<String, Long> zoneMap) throws Exception {
		if (zones == null) {
			return;
		}
		if (zones.isEmpty()) {
			volumeTypeZoneRepository.removeByVolumeTypeId(volumeTypeId);
			return;
		}
		List<VolumeTypeZone> relations = volumeTypeZoneRepository.listByVolumeTypeId(volumeTypeId);
		Map<Long, VolumeTypeZone> relationMap = Maps.newHashMap();
		for (VolumeTypeZone volumeTypeZone : relations) {
			relationMap.put(volumeTypeZone.getId(), volumeTypeZone);
		}
		for (String zone : zones) {
			VolumeTypeZone relation = volumeTypeZoneRepository.getByVolumeTypeIdAndZoneId(volumeTypeId,
					zoneMap.get(zone));
			if (null == relation) {
				if (zoneMap.get(zone) == null) {
					continue;
				}
				VolumeTypeZone newRelation = new VolumeTypeZone();
				newRelation.setVolumeTypeId(volumeTypeId);
				newRelation.setZoneId(zoneMap.get(zone));
				if (soldOutZones != null && soldOutZones.contains(zone)) {
					newRelation.setIsSoldOut(true);
				} else {
					newRelation.setIsSoldOut(false);
				}

				volumeTypeZoneRepository.save(newRelation);
			} else {
				relationMap.remove(relation.getId());
			}
		}
		for (Map.Entry<Long, VolumeTypeZone> entry : relationMap.entrySet()) {
			volumeTypeZoneRepository.remove(entry.getValue().getId());
		}

	}

	/**
	 * 同步镜像
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @param type
	 * @param imageMap
	 * @throws Exception
	 */
	private void syncImage(List<ImageModel> models, Long vendorId, String regionId, Long userId, String type,
			Map<String, Image> imageMap) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			imageRepository.removeByVid(vendorId, regionId, userId);
			return;
		}
		List<Image> images = imageRepository.listByVendorId(vendorId, regionId);
		Map<String, Image> imagesMap = Maps.newConcurrentMap();
		for (Image image : images) {
			if (null != image.getImageUuid()) {
				if (imagesMap.containsKey(image.getImageUuid())) {
					imageRepository.remove(image.getId(), userId);
				} else {
					imagesMap.put(image.getImageUuid(), image);
				}
			} else {
				imageRepository.remove(image.getId(), userId);
			}
		}
		List<Image> updateList = new ArrayList<Image>();
		List<Image> instertList = new ArrayList<Image>();
		for (ImageModel model : models) {
			Image image = new Image();
			// 过滤掉非active的镜像
			if ("ACTIVE".equalsIgnoreCase(model.getStatus())) {
				if (imagesMap.containsKey(model.getImageUuid())) {
					image = imagesMap.get(model.getImageUuid());
					BeanUtils.copyProperties(model, image);
					image.setMenderId(userId);
					image.setVendorType(type);
					image.setVendorId(vendorId);
					image.setRegionId(regionId);
					image.setDefaultUser(model.getDefaultUser());
					updateList.add(image);
					imagesMap.remove(model.getImageUuid());
					continue;
				}
				BeanUtils.copyProperties(model, image);
				image.setVendorId(vendorId);
				image.setCreatorId(userId);
				image.setVendorType(type);
				image.setRegionId(regionId);
				image.setMenderId(userId);
				image.setTenantId(0L);
				image.setProjectId(0L);
				if (!StringUtils.hasText(image.getOsCategory())) {
					image.setOsCategory(image.getOsCategory());
				} else {
					image.setOsCategory("Linux");
				}
				image.setCatalog("VM");
				instertList.add(image);
			} else {
				image = imagesMap.get(model.getImageUuid());
				if (null != image) {
					imageRepository.remove(image.getId(), userId);
				}
			}
		}
		if (!updateList.isEmpty()) {
			imageRepository.batchUpdate(updateList, updateList.size());
		}
		if (!instertList.isEmpty()) {
			imageRepository.batchSave(instertList, instertList.size());
		}
		for (Map.Entry<String, Image> set : imagesMap.entrySet()) {
			imageRepository.remove(set.getValue().getId(), userId);
		}
	}

	/**
	 * 同步规格
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @param regionId
	 * @throws Exception
	 */
	private void syncFlavor(List<FlavorModel> models, Long vendorId, Long userId, String regionId) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			flavorRepository.removeByVid(vendorId, regionId);
			return;
		}
		List<Flavor> flavors = flavorRepository.listByVendorId(vendorId, regionId);
		Map<String, Flavor> flavorMap = new HashMap<String, Flavor>(8);
		for (Flavor flavor : flavors) {
			flavorMap.put(flavor.getFlavorUuid(), flavor);
		}
		List<Flavor> updateList = new ArrayList<Flavor>();
		List<Flavor> instertList = new ArrayList<Flavor>();
		for (FlavorModel model : models) {
			Flavor flavor = new Flavor();
			if (flavorMap.containsKey(model.getFlavorUuid())) {
				flavor = flavorMap.get(model.getFlavorUuid());
				BeanUtils.copyProperties(model, flavor);
				flavor.setOsExtraSpecs(JSONObject.toJSONString(model.getOsExtraSpecs()));
				flavor.setAttachableQuantity(JSONObject.toJSONString(model.getAttachableQuantity()));
				flavor.setVendorId(vendorId);
				flavor.setRegionId(regionId);
				flavorRepository.update(flavor);
				flavorMap.remove(model.getName());
				continue;
			}
			BeanUtils.copyProperties(model, flavor);
			flavor.setOsExtraSpecs(JSONObject.toJSONString(model.getOsExtraSpecs()));
			flavor.setAttachableQuantity(JSONObject.toJSONString(model.getAttachableQuantity()));
			flavor.setVendorId(vendorId);
			flavor.setRegionId(regionId);
			flavorRepository.save(flavor);
		}

		for (Map.Entry<String, Flavor> entry : flavorMap.entrySet()) {
			flavorRepository.delete(entry.getValue().getId());
		}
	}

	/**
	 * 同步密钥
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncKeypair(List<KeypairModel> models, String regionId, Long vendorId, Long userId) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			keypairRepository.removeByVid(vendorId, regionId, userId);
			return;
		}
		List<Keypair> keypairs = keypairRepository.listByVid(vendorId, regionId);
		Map<String, Keypair> keypairMap = Maps.newHashMap();
		for (Keypair keypair : keypairs) {
			keypairMap.put(keypair.getName(), keypair);
		}
		for (KeypairModel model : models) {
			Keypair keypair = new Keypair();
			if (keypairMap.containsKey(model.getName())) {
				keypair = keypairMap.get(model.getName());
				BeanUtils.copyProperties(model, keypair);
				model.setGmtCreate(keypair.getGmtCreate());
				model.setUserUuid(keypair.getUserUuid());
				keypair.setMenderId(userId);
				keypair.setGmtModify(new Date());
				keypairRepository.update(keypair);
				keypairMap.remove(keypair.getName());
				continue;
			}
			BeanUtils.copyProperties(model, keypair);
			keypair.setCreatorId(userId);
			keypair.setGmtCreate(model.getGmtCreate());
			keypair.setVendorId(vendorId);
			keypair.setTenantId(0L);
			keypair.setProjectId(0L);
			keypairRepository.save(keypair);
		}
		for (Map.Entry<String, Keypair> entry : keypairMap.entrySet()) {
			keypairRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步端口
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncPort(List<PortModel> models, String regionId, Long vendorId, Long userId) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			portRepository.removeByVid(vendorId, regionId, userId);
			return;
		}
		List<Subnet> subnets = subnetRepository.listByRegion(vendorId, regionId);
		Map<String, Long> subnetMap = new HashMap<>(8);
		for (Subnet subnet : subnets) {
			subnetMap.put(subnet.getSubnetUuid(), subnet.getId());
		}
		List<Port> ports = portRepository.listByVid(vendorId, regionId);
		Map<String, Port> portMap = Maps.newHashMap();
		for (Port port : ports) {
			portMap.put(port.getPortUuid(), port);
		}
		for (PortModel model : models) {
			Port port = new Port();
			if (portMap.containsKey(model.getPortUuid())) {
				port = portMap.get(model.getPortUuid());
				BeanUtils.copyProperties(model, port);
				port.setGmtCreate(port.getGmtCreate());
				port.setMenderId(userId);
				port.setRegionId(regionId);
				port.setGmtModify(new Date());
				portRepository.update(port);
				portMap.remove(port.getPortUuid());
				continue;
			}
			BeanUtils.copyProperties(model, port);
			port.setCreatorId(userId);
			port.setRegionId(regionId);
			port.setGmtCreate(new Date());
			port.setVendorId(vendorId);
			portRepository.save(port);

			List<PortFixedIpModel> portFixedIpModels = model.getPortFixedIps();

			if (portFixedIpModels == null) {
				return;
			}
			if (portFixedIpModels.isEmpty()) {
				portFixedIpRepository.deleteByPortId(port.getId());
				return;
			}
			List<PortFixedIp> portFixedIps = portFixedIpRepository.listByPortId(port.getId());
			Map<String, PortFixedIp> portFixedIpMap = Maps.newHashMap();
			for (PortFixedIp portFixedIp : portFixedIps) {
				portFixedIpMap.put(portFixedIp.getSubnetUuid() + portFixedIp.getIpAddress(), portFixedIp);
			}
			for (PortFixedIpModel portFixedIpModel : portFixedIpModels) {
				PortFixedIp portFixedIp = new PortFixedIp();
				if (portFixedIpMap.containsKey(portFixedIpModel.getSubnetUuid() + portFixedIpModel.getIpAddress())) {
					portFixedIp = portFixedIpMap
							.get(portFixedIpModel.getSubnetUuid() + portFixedIpModel.getIpAddress());
					BeanUtils.copyProperties(portFixedIpModel, portFixedIp);
					portFixedIp.setPortId(port.getId());
					portFixedIp.setPortUuid(port.getPortUuid());
					portFixedIp.setSubnetId(subnetMap.get(portFixedIp.getSubnetUuid()));
					portFixedIpRepository.update(portFixedIp);
					portMap.remove(portFixedIp.getSubnetUuid() + portFixedIp.getIpAddress());
					continue;
				}
				BeanUtils.copyProperties(portFixedIpModel, portFixedIp);
				portFixedIp.setPortId(port.getId());
				portFixedIp.setPortUuid(port.getPortUuid());
				portFixedIp.setSubnetId(subnetMap.get(portFixedIp.getSubnetUuid()));
				portFixedIpRepository.save(portFixedIp);
			}
			for (Map.Entry<String, PortFixedIp> entry : portFixedIpMap.entrySet()) {
				portFixedIpRepository.delete(entry.getValue().getId());
			}
		}
		for (Map.Entry<String, Port> entry : portMap.entrySet()) {
			portRepository.remove(entry.getValue().getId(), userId);
		}
	}

	private void syncElasticIp(List<ElasticIpModel> models, String region, Long vendorId, Long userId)
			throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			elasticIpRepository.removeByVid(vendorId, userId, region);
			return;
		}
		List<ElasticIp> elasticIps = elasticIpRepository.listByVid(vendorId, region);
		Map<String, ElasticIp> elasticIpMap = Maps.newHashMap();
		for (ElasticIp elasticIp : elasticIps) {
			elasticIpMap.put(elasticIp.getElasticIpUuid(), elasticIp);
		}
		for (ElasticIpModel model : models) {
			ElasticIp elasticIp = new ElasticIp();
			if (elasticIpMap.containsKey(model.getElasticIpUuid())) {
				elasticIp = elasticIpMap.get(model.getElasticIpUuid());
				BeanUtils.copyProperties(model, elasticIp);
				elasticIp.setInstanceId(model.getPortId());
				elasticIp.setVendorId(vendorId);
				elasticIp.setGmtModify(new Date());
				elasticIp.setRegionId(region);
				elasticIpRepository.update(elasticIp);
				elasticIpMap.remove(elasticIp.getElasticIpUuid());
				continue;
			}
			BeanUtils.copyProperties(model, elasticIp);
			elasticIp.setInstanceId(model.getPortId());
			elasticIp.setCreatorId(0L);
			elasticIp.setMenderId(0L);
			elasticIp.setVendorId(vendorId);
			elasticIp.setGmtCreate(new Date());
			elasticIp.setRegionId(region);
			elasticIpRepository.save(elasticIp);
			elasticIpMap.remove(model.getElasticIpUuid());
		}
		for (Map.Entry<String, ElasticIp> entry : elasticIpMap.entrySet()) {
			elasticIpRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步nat网关
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncNatGateway(List<NatGatewayModel> models, String regionId, Long vendorId, Long userId,
			Map<String, Long> vpcMap, Map<String, Long> subnetMap) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			natGatewayRepository.removeByVid(vendorId, regionId, userId);
			return;
		}
		List<NatGateway> natGateways = natGatewayRepository.listByVendorId(vendorId, regionId);
		Map<String, NatGateway> natGatewayMap = Maps.newHashMap();
		for (NatGateway gateway : natGateways) {
			natGatewayMap.put(gateway.getUuid(), gateway);
		}
		List<NatGateway> updateList = new ArrayList<NatGateway>();
		List<NatGateway> instertList = new ArrayList<NatGateway>();
		for (NatGatewayModel model : models) {
			NatGateway natGateway = new NatGateway();
			if (natGatewayMap.containsKey(model.getUuid())) {
				natGateway = natGatewayMap.get(model.getUuid());
				BeanUtils.copyProperties(model, natGateway);
				natGateway.setMenderId(userId);
				natGateway.setGmtModify(new Date());
				natGateway.setVpcId(vpcMap.get(model.getVpcUuid()));
				natGateway.setSubnetId(subnetMap.get(model.getSubnetUuid()));
				updateList.add(natGateway);
				natGatewayMap.remove(natGateway.getUuid());
				continue;
			}
			BeanUtils.copyProperties(model, natGateway);
			natGateway.setCreatorId(userId);
			natGateway.setGmtCreate(model.getGmtCreate());
			natGateway.setVendorId(vendorId);
			natGateway.setVpcId(vpcMap.get(model.getVpcUuid()));
			natGateway.setSubnetId(subnetMap.get(model.getSubnetUuid()));
			instertList.add(natGateway);
		}
		if (!updateList.isEmpty()) {
			natGatewayRepository.batchUpdate(updateList);
		}
		if (!instertList.isEmpty()) {
			natGatewayRepository.batchSave(instertList);
		}
		for (Map.Entry<String, NatGateway> entry : natGatewayMap.entrySet()) {
			natGatewayRepository.delete(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步nat网关dnat规则
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncNatGatewayDnatRule(List<NatGatewayDnatRuleModel> models, String regionId, Long vendorId,
			Long userId, Map<String, Long> natGatewayMap, Map<String, Long> elasticIpMap, Map<String, Long> portMap)
			throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			dnatRuleRepository.removeByVid(vendorId, regionId, userId);
			return;
		}
		List<NatGatewayDnatRule> dnatRules = dnatRuleRepository.listByVendorId(vendorId, regionId);
		Map<String, NatGatewayDnatRule> dnatRuleMap = Maps.newHashMap();
		for (NatGatewayDnatRule dnatRule : dnatRules) {
			dnatRuleMap.put(dnatRule.getUuid(), dnatRule);
		}
		List<NatGatewayDnatRule> updateList = new ArrayList<NatGatewayDnatRule>();
		List<NatGatewayDnatRule> instertList = new ArrayList<NatGatewayDnatRule>();
		for (NatGatewayDnatRuleModel model : models) {
			NatGatewayDnatRule dnatRule = new NatGatewayDnatRule();
			if (dnatRuleMap.containsKey(model.getUuid())) {
				dnatRule = dnatRuleMap.get(model.getUuid());
				BeanUtils.copyProperties(model, dnatRule);
				dnatRule.setMenderId(userId);
				dnatRule.setGmtModify(new Date());
				dnatRule.setNatGatewayId(natGatewayMap.get(model.getNatGatewayId()));
				dnatRule.setElasticIpId(elasticIpMap.get(model.getFloatingIpId()));
				dnatRule.setPortId(portMap.get(model.getPortUuid()));
				updateList.add(dnatRule);
				dnatRuleMap.remove(dnatRule.getUuid());
				continue;
			}
			BeanUtils.copyProperties(model, dnatRule);
			dnatRule.setCreatorId(userId);
			dnatRule.setGmtCreate(model.getGmtCreate());
			dnatRule.setVendorId(vendorId);
			dnatRule.setNatGatewayId(natGatewayMap.get(model.getNatGatewayId()));
			dnatRule.setElasticIpId(elasticIpMap.get(model.getFloatingIpId()));
			dnatRule.setPortId(portMap.get(model.getPortUuid()));
			instertList.add(dnatRule);
		}
		if (!updateList.isEmpty()) {
			dnatRuleRepository.batchUpdate(updateList);
		}
		if (!instertList.isEmpty()) {
			dnatRuleRepository.batchSave(instertList);
		}
		for (Map.Entry<String, NatGatewayDnatRule> entry : dnatRuleMap.entrySet()) {
			dnatRuleRepository.delete(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步nat网关snat规则
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncNatGatewaySnatRule(List<NatGatewaySnatRuleModel> models, String regionId, Long vendorId,
			Long userId, Map<String, Long> natGatewayMap, Map<String, Long> elasticIpMap, Map<String, Long> subnetMap)
			throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			snatRuleRepository.removeByVid(vendorId, regionId, userId);
			return;
		}
		List<NatGatewaySnatRule> snatRules = snatRuleRepository.listByVendorId(vendorId, regionId);
		Map<String, NatGatewaySnatRule> snatRuleMap = Maps.newHashMap();
		for (NatGatewaySnatRule snatRule : snatRules) {
			snatRuleMap.put(snatRule.getUuid(), snatRule);
		}
		for (NatGatewaySnatRuleModel model : models) {
			NatGatewaySnatRule snatRule = new NatGatewaySnatRule();
			if (snatRuleMap.containsKey(model.getUuid())) {
				snatRule = snatRuleMap.get(model.getUuid());
				BeanUtils.copyProperties(model, snatRule);
				snatRule.setMenderId(userId);
				snatRule.setGmtModify(new Date());
				snatRule.setNatGatewayId(natGatewayMap.get(model.getNatGatewayId()));
				snatRule.setSubnetId(subnetMap.get(model.getSubnetUuid()));
				snatRuleRepository.update(snatRule);
				List<String> list = Arrays.asList(model.getFloatingIpId().split(",")).stream().map(s -> (s.trim()))
						.collect(Collectors.toList());
				this.syncSnatRuleRelation(list, snatRule.getId(), elasticIpMap);
				snatRuleMap.remove(snatRule.getUuid());
				continue;
			}
			BeanUtils.copyProperties(model, snatRule);
			snatRule.setCreatorId(userId);
			snatRule.setGmtCreate(model.getGmtCreate());
			snatRule.setVendorId(vendorId);
			snatRule.setNatGatewayId(natGatewayMap.get(model.getNatGatewayId()));
			snatRule.setSubnetId(subnetMap.get(model.getSubnetUuid()));
			snatRuleRepository.save(snatRule);
			snatRuleMap.remove(model.getUuid());
			List<String> list = Arrays.asList(model.getFloatingIpId().split(",")).stream().map(s -> (s.trim()))
					.collect(Collectors.toList());
			this.syncSnatRuleRelation(list, snatRule.getId(), elasticIpMap);
		}
		for (Map.Entry<String, NatGatewaySnatRule> entry : snatRuleMap.entrySet()) {
			snatRuleRepository.delete(entry.getValue().getId(), userId);
			ruleRelationRepository.removeBySnatRuleId(entry.getValue().getId());
		}
	}

	private void syncSnatRuleRelation(List<String> elasticIpIds, Long snatRuleId, Map<String, Long> elasticIpMap)
			throws Exception {
		if (elasticIpIds == null) {
			return;
		}
		if (elasticIpIds.isEmpty()) {
			ruleRelationRepository.removeBySnatRuleId(snatRuleId);
			return;
		}
		List<NatGatewaySnatRuleRelation> relations = ruleRelationRepository.listBySnatRuleId(snatRuleId);
		Map<Long, NatGatewaySnatRuleRelation> ruleRelationMap = Maps.newHashMap();
		for (NatGatewaySnatRuleRelation snatRule : relations) {
			ruleRelationMap.put(snatRule.getId(), snatRule);
		}
		for (String elasticIpId : elasticIpIds) {
			NatGatewaySnatRuleRelation ruleRelation = ruleRelationRepository.getBySnatRuleIdAndElasticIpId(snatRuleId,
					elasticIpMap.get(elasticIpId));
			if (null == ruleRelation) {
				NatGatewaySnatRuleRelation relation = new NatGatewaySnatRuleRelation();
				relation.setSnatRuleId(snatRuleId);
				relation.setElasticIpId(elasticIpMap.get(elasticIpId));
				ruleRelationRepository.save(relation);
			} else {
				ruleRelationMap.remove(ruleRelation.getId());
			}
		}
		for (Map.Entry<Long, NatGatewaySnatRuleRelation> entry : ruleRelationMap.entrySet()) {
			ruleRelationRepository.remove(entry.getValue().getId());
		}

	}

	/**
	 * 同步负载均衡
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncLoadBalancer(List<LbModel> models, Map<String, Long> vpcMap, Map<String, Subnet> neutronSubnetMap,
			Long vendorId, Long userId, String region) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			loadBalancerRepository.removeByVid(vendorId, region, userId);
			return;
		}
		List<LoadBalancer> balancers = loadBalancerRepository.listByVid(vendorId, region);
		Map<String, LoadBalancer> balancerMap = Maps.newHashMap();
		for (LoadBalancer balancer : balancers) {
			balancerMap.put(balancer.getLbUuid(), balancer);
		}
		for (LbModel model : models) {
			LoadBalancer balancer = new LoadBalancer();
			if (balancerMap.containsKey(model.getLbUuid())) {
				balancer = balancerMap.get(model.getLbUuid());
				BeanUtils.copyProperties(model, balancer);
				balancer.setVpcId(vpcMap.get(balancer.getVpcUuid()));
				balancer.setSubnetId(neutronSubnetMap.get(balancer.getVipSubnetUuid()).getId());
				balancer.setSubnetUuid(neutronSubnetMap.get(balancer.getVipSubnetUuid()).getSubnetUuid());
				balancer.setVpcId(neutronSubnetMap.get(balancer.getVipSubnetUuid()).getVpcId());
				balancer.setVpcUuid(neutronSubnetMap.get(balancer.getVipSubnetUuid()).getVpcUuid());
				balancer.setMenderId(userId);
				balancer.setVendorId(vendorId);
				balancer.setGmtModify(new Date());
				balancer.setRegion(region);
				loadBalancerRepository.update(balancer);
				balancerMap.remove(balancer.getLbUuid());
				continue;
			}
			BeanUtils.copyProperties(model, balancer);
			balancer.setVpcId(vpcMap.get(balancer.getVpcUuid()));
			balancer.setSubnetId(neutronSubnetMap.get(balancer.getVipSubnetUuid()).getId());
			balancer.setSubnetUuid(neutronSubnetMap.get(balancer.getVipSubnetUuid()).getSubnetUuid());
			balancer.setVpcId(neutronSubnetMap.get(balancer.getVipSubnetUuid()).getVpcId());
			balancer.setVpcUuid(neutronSubnetMap.get(balancer.getVipSubnetUuid()).getVpcUuid());
			balancer.setCreatorId(userId);
			balancer.setVendorId(vendorId);
			balancer.setGmtCreate(new Date());
			balancer.setRegion(region);
			loadBalancerRepository.save(balancer);
			balancerMap.remove(balancer.getLbUuid());
		}
		for (Map.Entry<String, LoadBalancer> entry : balancerMap.entrySet()) {
			loadBalancerRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步监听器
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncLbListener(List<LbListenerModel> models, Map<String, Long> balancerMap, Long vendorId, Long userId,
			String region) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			lbListenerRepository.removeByVid(vendorId, userId, region);
			return;
		}
		List<LbListener> listenerList = lbListenerRepository.listByVid(vendorId, region);
		Map<String, LbListener> listenerMap = Maps.newHashMap();
		for (LbListener lbListener : listenerList) {
			listenerMap.put(lbListener.getListenerUuid(), lbListener);
		}
		for (LbListenerModel model : models) {
			LbListener lbListener = new LbListener();
			if (listenerMap.containsKey(model.getListenerUuid())) {
				lbListener = listenerMap.get(model.getListenerUuid());
				BeanUtils.copyProperties(model, lbListener);
				lbListener.setLbId(balancerMap.get(lbListener.getLbUuid()));
				lbListener.setVendorId(vendorId);
				lbListener.setGmtModify(new Date());
				lbListener.setRegionId(region);
				lbListenerRepository.update(lbListener);
				listenerMap.remove(model.getListenerUuid());
				continue;
			}
			BeanUtils.copyProperties(model, lbListener);
			lbListener.setLbId(balancerMap.get(lbListener.getLbUuid()));

			lbListener.setVendorId(vendorId);
			lbListener.setRegionId(region);
			lbListenerRepository.save(lbListener);
			listenerMap.remove(model.getListenerUuid());
		}
		for (Map.Entry<String, LbListener> entry : listenerMap.entrySet()) {
			lbListenerRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 后端云服务器组
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncLbPool(List<LbPoolModel> models, Map<String, Long> listenerMap, Map<String, Long> balancerMap,
			Long vendorId, Long userId, String region) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			lbPoolRepository.removeByVid(vendorId, userId, region);
			return;
		}
		List<LbPool> lbTargetGroups = lbPoolRepository.listByVid(vendorId, region);
		Map<String, LbPool> targetGroupMap = Maps.newHashMap();
		for (LbPool lbTargetGroup : lbTargetGroups) {
			targetGroupMap.put(lbTargetGroup.getPoolUuid(), lbTargetGroup);
		}
		for (LbPoolModel model : models) {
			LbPool lbTargetGroup = new LbPool();
			if (targetGroupMap.containsKey(model.getPoolUuid())) {
				lbTargetGroup = targetGroupMap.get(model.getPoolUuid());
				BeanUtils.copyProperties(model, lbTargetGroup);
				lbTargetGroup.setListenerId(listenerMap.get(lbTargetGroup.getListenerUuid()));
				lbTargetGroup.setLbId(balancerMap.get(lbTargetGroup.getLbUuid()));
				lbTargetGroup.setMenderId(userId);
				lbTargetGroup.setVendorId(vendorId);
				lbTargetGroup.setGmtModify(new Date());
				lbTargetGroup.setRegionId(region);
				lbPoolRepository.update(lbTargetGroup);
				targetGroupMap.remove(lbTargetGroup.getPoolUuid());
				continue;
			}
			BeanUtils.copyProperties(model, lbTargetGroup);
			lbTargetGroup.setListenerId(listenerMap.get(lbTargetGroup.getListenerUuid()));
			lbTargetGroup.setLbId(balancerMap.get(lbTargetGroup.getLbUuid()));
			lbTargetGroup.setCreatorId(userId);
			lbTargetGroup.setVendorId(vendorId);
			lbTargetGroup.setGmtCreate(new Date());
			lbTargetGroup.setRegionId(region);
			lbPoolRepository.save(lbTargetGroup);
			targetGroupMap.remove(lbTargetGroup.getPoolUuid());
		}
		for (Map.Entry<String, LbPool> entry : targetGroupMap.entrySet()) {
			lbPoolRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 后端云服务器
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncLbMember(List<LbMemberModel> models, Map<String, LbPool> tgMap,
			Map<String, Subnet> neutronSubnetMap, Long vendorId, Long userId, String region) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			lbMemberRepository.removeByVid(vendorId, userId, region);
			return;
		}
		List<LbMember> lbTargets = lbMemberRepository.listByVid(vendorId, region);
		Map<String, LbMember> targetMap = Maps.newHashMap();
		for (LbMember lbTarget : lbTargets) {
			targetMap.put(lbTarget.getPoolUuid() + lbTarget.getMemberUuid(), lbTarget);
		}
		for (LbMemberModel model : models) {
			LbMember lbTarget = new LbMember();
			String uuid = model.getPoolUuid() + model.getMemberUuid();
			if (targetMap.containsKey(uuid)) {
				lbTarget = targetMap.get(uuid);
				BeanUtils.copyProperties(model, lbTarget);
				LbPool pool = tgMap.get(lbTarget.getPoolUuid());
				if (null != pool) {
					lbTarget.setPoolId(pool.getId());
					lbTarget.setListenerId(pool.getListenerId());
				}
				Subnet subnet = neutronSubnetMap.get(lbTarget.getSubnetUuid());
				if (null != subnet) {
					lbTarget.setSubnetId(subnet.getId());
				}
				PortFixedIp portFixedIp = portFixedIpRepository.getPortFixedBySubnet(lbTarget.getSubnetUuid(), lbTarget.getAddress());
				if(null != portFixedIp) {
					Port port = portRepository.query(portFixedIp.getPortId());
					if(null != port && port.getDeviceOwner().contains("compute")) {
						CloudServer cloudServer = cloudServerRepository.get(vendorId, port.getDeviceUuid());
						if(null != cloudServer) {
							lbTarget.setName(cloudServer.getName());
							lbTarget.setStatus(cloudServer.getStatus());
							lbTarget.setInstanceId(cloudServer.getInstanceId());
						}
					}
				}
				lbTarget.setVendorId(vendorId);
				lbTarget.setGmtModify(new Date());
				lbTarget.setRegionId(region);
				lbMemberRepository.update(lbTarget);
				targetMap.remove(uuid);
				continue;
			}
			BeanUtils.copyProperties(model, lbTarget);
			LbPool pool = tgMap.get(lbTarget.getPoolUuid());
			if (null != pool) {
				lbTarget.setPoolId(pool.getId());
				lbTarget.setListenerId(pool.getListenerId());
			}
			Subnet subnet = neutronSubnetMap.get(lbTarget.getSubnetUuid());
			if (null != subnet) {
				lbTarget.setSubnetId(subnet.getId());
			}
			PortFixedIp portFixedIp = portFixedIpRepository.getPortFixedBySubnet(lbTarget.getSubnetUuid(), lbTarget.getAddress());
			if(null != portFixedIp) {
				Port port = portRepository.query(portFixedIp.getPortId());
				if(null != port && port.getDeviceOwner().contains("compute")) {
					CloudServer cloudServer = cloudServerRepository.get(vendorId, port.getDeviceUuid());
					if(null != cloudServer) {
						lbTarget.setName(cloudServer.getName());
						lbTarget.setStatus(cloudServer.getStatus());
						lbTarget.setInstanceId(cloudServer.getInstanceId());
					}
				}
			}

			lbTarget.setCreatorId(0L);
			lbTarget.setVendorId(vendorId);
			lbTarget.setGmtCreate(new Date());
			lbTarget.setRegionId(region);
			lbMemberRepository.save(lbTarget);
			targetMap.remove(lbTarget.getPoolUuid() + lbTarget.getMemberUuid());
		}
		for (Map.Entry<String, LbMember> entry : targetMap.entrySet()) {
			lbMemberRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 后端云服务器
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncHealthMonitor(List<HealthMonitorModel> models, Map<String, LbPool> lbPoolMap, Long vendorId,
			Long userId, String region) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			healthMonitorRepository.removeByVid(vendorId, userId, region);
			return;
		}
		List<HealthMonitor> lbTargets = healthMonitorRepository.listByVid(vendorId, region);
		Map<String, HealthMonitor> targetMap = Maps.newHashMap();
		for (HealthMonitor lbTarget : lbTargets) {
			targetMap.put(lbTarget.getPoolUuid() + lbTarget.getHealthUuid(), lbTarget);
		}
		for (HealthMonitorModel model : models) {
			HealthMonitor lbTarget = new HealthMonitor();
			if (targetMap.containsKey(model.getPoolUuid() + model.getHealthUuid())) {
				lbTarget = targetMap.get(model.getPoolUuid() + model.getHealthUuid());
				BeanUtils.copyProperties(model, lbTarget);
				LbPool lbPool = lbPoolMap.get(lbTarget.getPoolUuid());
				if (null != lbPool) {
					lbTarget.setPoolId(lbPool.getId());
					lbTarget.setListenerId(lbPool.getListenerId());
				}

				lbTarget.setMenderId(userId);
				lbTarget.setVendorId(vendorId);
				lbTarget.setGmtModify(new Date());
				lbTarget.setRegionId(region);
				healthMonitorRepository.update(lbTarget);
				targetMap.remove(lbTarget.getPoolUuid() + lbTarget.getHealthUuid());
				continue;
			}
			BeanUtils.copyProperties(model, lbTarget);
			LbPool lbPool = lbPoolMap.get(lbTarget.getPoolUuid());
			if (null != lbPool) {
				lbTarget.setPoolId(lbPool.getId());
				lbTarget.setListenerId(lbPool.getListenerId());
			}
			lbTarget.setCreatorId(userId);
			lbTarget.setVendorId(vendorId);
			lbTarget.setGmtCreate(new Date());
			lbTarget.setRegionId(region);
			healthMonitorRepository.save(lbTarget);
			targetMap.remove(lbTarget.getPoolUuid() + lbTarget.getHealthUuid());
		}
		for (Map.Entry<String, HealthMonitor> entry : targetMap.entrySet()) {
			healthMonitorRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 转发策略
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncL7policy(List<LbListenerPolicyModel> models, Map<String, Long> lbPoolMap,
			Map<String, Long> listenerMap, Long vendorId, Long userId, String region) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			lbListenerPolicyRepository.removeByVid(vendorId, userId, region);
			return;
		}
		List<LbListenerPolicy> lbTargets = lbListenerPolicyRepository.listByVid(vendorId, region);
		Map<String, LbListenerPolicy> targetMap = Maps.newHashMap();
		for (LbListenerPolicy lbTarget : lbTargets) {
			targetMap.put(lbTarget.getPolicyUuid(), lbTarget);
		}
		for (LbListenerPolicyModel model : models) {
			LbListenerPolicy lbTarget = new LbListenerPolicy();
			if (targetMap.containsKey(model.getPolicyUuid())) {
				lbTarget = targetMap.get(model.getPolicyUuid());
				BeanUtils.copyProperties(model, lbTarget);
				lbTarget.setListenerId(listenerMap.get(lbTarget.getListenerUuid()));
				lbTarget.setRedirectListenerId(listenerMap.get(lbTarget.getRedirectListenerUuid()));
				lbTarget.setRedirectPoolId(lbPoolMap.get(lbTarget.getRedirectPoolUuid()));
				lbTarget.setMenderId(userId);
				lbTarget.setVendorId(vendorId);
				lbTarget.setGmtModify(new Date());
				lbTarget.setRegionId(region);
				lbListenerPolicyRepository.update(lbTarget);
				targetMap.remove(lbTarget.getPolicyUuid());
				continue;
			}
			BeanUtils.copyProperties(model, lbTarget);
			lbTarget.setListenerId(listenerMap.get(lbTarget.getListenerUuid()));
			lbTarget.setRedirectListenerId(listenerMap.get(lbTarget.getRedirectListenerUuid()));
			lbTarget.setRedirectPoolId(lbPoolMap.get(lbTarget.getRedirectPoolUuid()));
			lbTarget.setCreatorId(userId);
			lbTarget.setVendorId(vendorId);
			lbTarget.setGmtCreate(new Date());
			lbTarget.setRegionId(region);
			lbListenerPolicyRepository.save(lbTarget);
			targetMap.remove(lbTarget.getPolicyUuid());
		}
		for (Map.Entry<String, LbListenerPolicy> entry : targetMap.entrySet()) {
			lbListenerPolicyRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 准发规则
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncL7rule(List<LbListenerRuleModel> models, Map<String, Long> lbPolicyMap, Long vendorId, Long userId,
			String region) throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			lbListenerRuleRepository.removeByVid(vendorId, userId, region);
			return;
		}
		List<LbListenerRule> lbTargets = lbListenerRuleRepository.listByVid(vendorId, region);
		Map<String, LbListenerRule> targetMap = Maps.newHashMap();
		for (LbListenerRule lbTarget : lbTargets) {
			targetMap.put(lbTarget.getRuleUuid() + lbTarget.getPolicyUuid(), lbTarget);
		}
		for (LbListenerRuleModel model : models) {
			LbListenerRule lbTarget = new LbListenerRule();
			if (targetMap.containsKey(lbTarget.getRuleUuid() + lbTarget.getPolicyUuid())) {
				lbTarget = targetMap.get(lbTarget.getRuleUuid() + lbTarget.getPolicyUuid());
				BeanUtils.copyProperties(model, lbTarget);
				lbTarget.setPolicyId(lbPolicyMap.get(lbTarget.getPolicyUuid()));

				lbTarget.setMenderId(userId);
				lbTarget.setVendorId(vendorId);
				lbTarget.setGmtModify(new Date());
				lbTarget.setRegionId(region);
				lbListenerRuleRepository.update(lbTarget);
				targetMap.remove(lbTarget.getRuleUuid() + lbTarget.getPolicyUuid());
				continue;
			}
			BeanUtils.copyProperties(model, lbTarget);
			lbTarget.setPolicyId(lbPolicyMap.get(lbTarget.getPolicyUuid()));
			lbTarget.setCreatorId(userId);
			lbTarget.setVendorId(vendorId);
			lbTarget.setGmtCreate(new Date());
			lbTarget.setRegionId(region);
			lbListenerRuleRepository.save(lbTarget);
			targetMap.remove(lbTarget.getRuleUuid() + lbTarget.getPolicyUuid());
		}
		for (Map.Entry<String, LbListenerRule> entry : targetMap.entrySet()) {
			lbListenerRuleRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步标签
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncTag(List<TagModel> models, Long vendorId, Long userId, String region, String resourceId)
			throws Exception {
		if (models == null) {
			return;
		}
		if (models.isEmpty()) {
			tagRepository.removeByRes(vendorId, region, resourceId, "");
			return;
		}
		List<Tag> tagList = tagRepository.listByRes(vendorId, region, resourceId, "");
		Map<String, Tag> tagMap = Maps.newHashMap();
		for (Tag tag : tagList) {
			tagMap.put(tag.getKey() + tag.getResourceId(), tag);
		}
		for (TagModel model : models) {
			Tag tag = new Tag();
			if (tagMap.containsKey(model.getKey() + model.getResourceId())) {
				tag = tagMap.get(model.getKey() + model.getResourceId());
				BeanUtils.copyProperties(model, tag);
				tag.setResourceType(model.getResourceType());
				tag.setVendorId(vendorId);
				tag.setGmtModify(new Date());
				tag.setRegionId(region);
				tagRepository.update(tag);
				tagMap.remove(model.getKey() + model.getResourceId());
				continue;
			}
			BeanUtils.copyProperties(model, tag);
			tag.setResourceType(model.getResourceType());
			tag.setVendorId(vendorId);
			tag.setRegionId(region);
			tagRepository.save(tag);
			tagMap.remove(model.getKey() + model.getResourceId());
		}
		for (Map.Entry<String, Tag> entry : tagMap.entrySet()) {
			tagRepository.remove(entry.getValue().getId());
		}
	}

}
