package com.bocloud.ims.service.transportor;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.AddressBean;
import com.bocloud.cmp.model.FirewallModel;
import com.bocloud.cmp.model.FirewallPolicyModel;
import com.bocloud.cmp.model.FirewallRuleModel;
import com.bocloud.cmp.model.FlavorModel;
import com.bocloud.cmp.model.FloatingIpModel;
import com.bocloud.cmp.model.HostModel;
import com.bocloud.cmp.model.ImageModel;
import com.bocloud.cmp.model.KeypairModel;
import com.bocloud.cmp.model.ManageOneSyncModel;
import com.bocloud.cmp.model.NetworkBean;
import com.bocloud.cmp.model.NetworkModel;
import com.bocloud.cmp.model.PortFixedIpModel;
import com.bocloud.cmp.model.PortModel;
import com.bocloud.cmp.model.RegionModel;
import com.bocloud.cmp.model.RouterModel;
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.StorageModel;
import com.bocloud.cmp.model.SubnetModel;
import com.bocloud.cmp.model.VolumeModel;
import com.bocloud.cmp.model.VolumeTypeModel;
import com.bocloud.cmp.model.VpcModel;
import com.bocloud.cmp.model.manageone.VdcModel;
import com.bocloud.cmp.model.manageone.VdcProjectModel;
import com.bocloud.cmp.provider.utils.IPAddress;
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.CloudServer;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.Firewall;
import com.bocloud.ims.entity.resource.FirewallPolicy;
import com.bocloud.ims.entity.resource.FirewallRule;
import com.bocloud.ims.entity.resource.Flavor;
import com.bocloud.ims.entity.resource.FloatingIp;
import com.bocloud.ims.entity.resource.Image;
import com.bocloud.ims.entity.resource.Ip;
import com.bocloud.ims.entity.resource.Ip.IpStatus;
import com.bocloud.ims.entity.resource.IpPool;
import com.bocloud.ims.entity.resource.Keypair;
import com.bocloud.ims.entity.resource.Network;
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.Router;
import com.bocloud.ims.entity.resource.RouterSubnet;
import com.bocloud.ims.entity.resource.SecurityGroup;
import com.bocloud.ims.entity.resource.SecurityGroupRule;
import com.bocloud.ims.entity.resource.Server;
import com.bocloud.ims.entity.resource.ServerConfig;
import com.bocloud.ims.entity.resource.ServerSgroup;
import com.bocloud.ims.entity.resource.Snapshot;
import com.bocloud.ims.entity.resource.Storage;
import com.bocloud.ims.entity.resource.Subnet;
import com.bocloud.ims.entity.resource.Volume;
import com.bocloud.ims.entity.resource.Vpc;
import com.bocloud.ims.entity.resource.manageone.ManageOneProject;
import com.bocloud.ims.entity.resource.manageone.ManageOneVdc;
import com.bocloud.ims.interfaces.resource.IpService;
import com.bocloud.ims.repository.manageone.ManageOneProjectRepository;
import com.bocloud.ims.repository.manageone.ManageOneVdcRepository;
import com.bocloud.ims.repository.resource.CloudServerRepository;
import com.bocloud.ims.repository.resource.FirewallPolicyRepository;
import com.bocloud.ims.repository.resource.FirewallRepository;
import com.bocloud.ims.repository.resource.FirewallRuleRepository;
import com.bocloud.ims.repository.resource.FlavorRepository;
import com.bocloud.ims.repository.resource.FloatingIpRepository;
import com.bocloud.ims.repository.resource.ImageRepository;
import com.bocloud.ims.repository.resource.IpPoolRepository;
import com.bocloud.ims.repository.resource.IpRepository;
import com.bocloud.ims.repository.resource.KeypairRepository;
import com.bocloud.ims.repository.resource.NetworkRepository;
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.RouterRepository;
import com.bocloud.ims.repository.resource.RouterSubnetRepository;
import com.bocloud.ims.repository.resource.SecurityGroupRepository;
import com.bocloud.ims.repository.resource.SecurityGroupRuleRepository;
import com.bocloud.ims.repository.resource.ServerConfigRepository;
import com.bocloud.ims.repository.resource.ServerLabelRepository;
import com.bocloud.ims.repository.resource.ServerRepository;
import com.bocloud.ims.repository.resource.ServerSgroupRepository;
import com.bocloud.ims.repository.resource.SnapshotRepository;
import com.bocloud.ims.repository.resource.StorageRepository;
import com.bocloud.ims.repository.resource.SubnetRepository;
import com.bocloud.ims.repository.resource.TenantNetworkRepository;
import com.bocloud.ims.repository.resource.VolumeRepository;
import com.bocloud.ims.repository.resource.VolumeTypeRepository;
import com.bocloud.ims.repository.resource.VpcRepository;
import com.bocloud.ims.service.utils.ServerOperationHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 华为云同步类
 *
 * @author wangyu
 * @version 4.1.0-SNAPSHOT
 * @since 2018/9/25
 */
public class ManageOneTransportor {

	private static Logger logger = LoggerFactory.getLogger(ManageOneTransportor.class);
	private NetworkRepository networkRepository;
	private SnapshotRepository snapshotRepository;
	private ImageRepository imageRepository;
	private FlavorRepository flavorRepository;
	private CloudServerRepository cloudServerRepository;
	private SubnetRepository subnetRepository;
	private RegionRepository regionRepository;
	private VolumeRepository volumeRepository;
	private VolumeTypeRepository volumeTypeRepository;
	private PortRepository portRepository;
	private RouterRepository routerRepository;
	private ResourceRepository resourceRepository;
	private IpRepository ipRepository;
	private SecurityGroupRepository securityGroupRepository;
	private SecurityGroupRuleRepository securityGroupRuleRepository;
	private ServerSgroupRepository serverSgroupRepository;
	private PortFixedIpRepository portFixedIpRepository;
	private KeypairRepository keypairRepository;
	private TenantNetworkRepository tenantNetworkRepository;
	private RouterSubnetRepository routerSubnetRepository;
	/* private AmqpTemplate amqpTemplate; */
	private ServerOperationHelper serverOperationHelper;
	private IpPoolRepository ipPoolRepository;
	private ServerLabelRepository serverLabelRepository;
	private IpService ipService;
	private ServerRepository serverRepository;
	private ServerConfigRepository serverConfigRepository;
	private FloatingIpRepository floatingIpRepository;
	private FirewallRepository firewallRepository;
	private FirewallPolicyRepository firewallPolicyRepository;
	private FirewallRuleRepository firewallRuleRepository;
	private ManageOneVdcRepository vdcRepository;
	private ManageOneProjectRepository projectRepository;
	private VpcRepository vpcRepository;
	private StorageRepository storageRepository;

	/**
	 *
	 */
	public ManageOneTransportor() {
	}

	/**
	 * @param subnetRepository
	 * @param portRepository
	 * @param ipRepository
	 * @param ipPoolRepository
	 * @param portFixedIpRepository
	 */
	public ManageOneTransportor(SubnetRepository subnetRepository, PortRepository portRepository,
			IpRepository ipRepository, IpPoolRepository ipPoolRepository, PortFixedIpRepository portFixedIpRepository) {
		super();
		this.subnetRepository = subnetRepository;
		this.portRepository = portRepository;
		this.ipRepository = ipRepository;
		this.ipPoolRepository = ipPoolRepository;
		this.portFixedIpRepository = portFixedIpRepository;
	}

	/**
	 * @param ipRepository
	 * @param ipPoolRepository
	 * @param subnetRepository
	 * @param portFixedIpRepository
	 */
	public ManageOneTransportor(IpRepository ipRepository, IpPoolRepository ipPoolRepository,
			SubnetRepository subnetRepository, PortFixedIpRepository portFixedIpRepository) {
		super();
		this.ipRepository = ipRepository;
		this.ipPoolRepository = ipPoolRepository;
		this.subnetRepository = subnetRepository;
		this.portFixedIpRepository = portFixedIpRepository;
	}

	public ManageOneTransportor(NetworkRepository networkRepository, SnapshotRepository snapshotRepository,
			ImageRepository imageRepository, FlavorRepository flavorRepository,
			CloudServerRepository cloudServerRepository, SubnetRepository subnetRepository,
			RegionRepository regionRepository, VolumeRepository volumeRepository, PortRepository portRepository,
			RouterRepository routerRepository, ResourceRepository resourceRepository, IpRepository ipRepository,
			SecurityGroupRepository securityGroupRepository, SecurityGroupRuleRepository securityGroupRuleRepository,
			ServerSgroupRepository serverSgroupRepository, PortFixedIpRepository portFixedIpRepository,
			KeypairRepository keypairRepository, TenantNetworkRepository tenantNetworkRepository,
			RouterSubnetRepository routerSubnetRepository, ServerOperationHelper serverOperationHelper,
			IpPoolRepository ipPoolRepository, ServerLabelRepository serverLabelRepository, IpService ipService,
			ServerRepository serverRepository, ServerConfigRepository serverConfigRepository,
			FloatingIpRepository floatingIpRepository, VolumeTypeRepository volumeTypeRepository,
			FirewallRepository firewallRepository, FirewallPolicyRepository firewallPolicyRepository,
			FirewallRuleRepository firewallRuleRepository, ManageOneVdcRepository vdcRepository,
			ManageOneProjectRepository projectRepository, VpcRepository vpcRepository,
			StorageRepository storageRepository) {
		this.serverRepository = serverRepository;
		this.serverConfigRepository = serverConfigRepository;
		this.networkRepository = networkRepository;
		this.snapshotRepository = snapshotRepository;
		this.imageRepository = imageRepository;
		this.flavorRepository = flavorRepository;
		this.cloudServerRepository = cloudServerRepository;
		this.subnetRepository = subnetRepository;
		this.regionRepository = regionRepository;
		this.volumeRepository = volumeRepository;
		this.portRepository = portRepository;
		this.routerRepository = routerRepository;
		this.resourceRepository = resourceRepository;
		this.ipRepository = ipRepository;
		this.securityGroupRepository = securityGroupRepository;
		this.securityGroupRuleRepository = securityGroupRuleRepository;
		this.serverSgroupRepository = serverSgroupRepository;
		this.portFixedIpRepository = portFixedIpRepository;
		this.keypairRepository = keypairRepository;
		this.tenantNetworkRepository = tenantNetworkRepository;
		this.routerSubnetRepository = routerSubnetRepository;
		/* this.amqpTemplate = amqpTemplate; */
		this.serverOperationHelper = serverOperationHelper;
		this.ipPoolRepository = ipPoolRepository;
		this.serverLabelRepository = serverLabelRepository;
		this.ipService = ipService;
		this.floatingIpRepository = floatingIpRepository;
		this.volumeTypeRepository = volumeTypeRepository;
		this.firewallRepository = firewallRepository;
		this.firewallPolicyRepository = firewallPolicyRepository;
		this.firewallRuleRepository = firewallRuleRepository;
		this.vdcRepository = vdcRepository;
		this.projectRepository = projectRepository;
		this.vpcRepository = vpcRepository;
		this.storageRepository = storageRepository;
	}

	public BocloudResult sync(CloudVendor vendor, Object data, Long userId) {
		/*
		 * CmdbModel cmdbModel = new CmdbModel();
		 * cmdbModel.setUuid(IDFactory.instance().uuid());
		 * cmdbModel.setServiceName(BoCloudService.IMS.name());
		 * cmdbModel.setUserId(userId); List<CmdbInfo> infos = Lists.newArrayList();
		 * infos.add(CmdbInfoConvertor.getInfo(vendor, null, null));
		 */
		try {
			if (null != data) {
				Long vendorId = vendor.getId();
				if (cloudServerRepository.hasBuilding(vendorId)) {
					return new BocloudResult(false, "该平台下有虚拟机正在创建，请稍后进行同步操作");
				}
				if (volumeRepository.hasBuilding(vendorId)) {
					return new BocloudResult(false, "该平台下有卷正在创建，请稍后进行同步操作");
				}
				if (snapshotRepository.hasBuilding(vendorId)) {
					return new BocloudResult(false, "该平台下有快照正在创建，请稍后进行同步操作");
				}
				if (imageRepository.hasBuilding(vendorId)) {
					return new BocloudResult(false, "该平台下有镜像正在制作，请稍后进行同步操作");
				}
				String content = JSONObject.toJSONString(data);
				ManageOneSyncModel model = JSONObject.parseObject(content, ManageOneSyncModel.class);
				// 同步可用区域
				logger.info("Starting sync region......");
				this.syncRegions(model.getRegions(), vendorId, userId);
				logger.info("End sync region......");
				// 同步规格
				logger.info("Starting sync flavor......");
				this.syncFlavor(model.getFlavorModels(), vendorId, userId);
				logger.info("End sync flavor......");
				// 同步密钥
				logger.info("Starting sync keypair......");
				this.syncKeypair(model.getKeypairModels(), vendorId, userId);
				logger.info("End sync keypair...");
				// 同步网络
				logger.info("Starting sync network......");
				this.syncNetwork(model.getNetworkModels(), vendorId, userId);
				logger.info("End sync network......");
				// 获取平台网络信息
				Map<String, Long> networkMap = Maps.newHashMap();
				List<Network> networks = networkRepository.listByVid(vendorId);
				for (Network network : networks) {
					networkMap.put(network.getNetworkUuid(), network.getId());
				}
				// 获取平台网络子网信息
				Map<String, Long> subnetMap = Maps.newHashMap();
				List<Subnet> subnets = subnetRepository.listByVid(vendorId);
				for (Subnet subnet : subnets) {
					subnetMap.put(subnet.getSubnetUuid(), subnet.getId());
				}
				// 同步端口
				logger.info("Starting sync port......");
				this.syncPort(model.getPortModels(), vendorId, userId, networkMap, subnetMap);
				logger.info("End sync port......");
				// 获取平台网络端口信息
				Map<String, Long> portMap = Maps.newHashMap();
				List<Port> ports = portRepository.listByVid(vendorId);
				for (Port port : ports) {
					portMap.put(port.getPortUuid(), port.getId());
				}
				// 同步VPC
				logger.info("Starting sync vpc......");
				// this.syncVpc(model.getVpcModels(), vendorId, userId,
				// networkMap);
				logger.info("End sync vpc......");
				// 同步路由
				logger.info("Starting sync router......");
				this.syncRouter(model.getRouterModels(), vendorId, userId, networkMap);
				logger.info("End sync router......");
				// 获取平台路由信息
				Map<String, Router> routerMap = Maps.newHashMap();
				List<Router> routers = routerRepository.listByVid(vendorId);
				for (Router router : routers) {
					routerMap.put(router.getRouterUuid(), router);
				}
				// 获取子网和路由的关系
				Map<String, String> srMap = Maps.newHashMap();
				List<Port> portList = portRepository.listPortIsNotExternal(vendorId);
				for (Port port : portList) {
					List<PortFixedIp> portFixedIps = portFixedIpRepository.listByPortId(port.getId());
					if (!ListTool.isEmpty(portFixedIps)) {
						for (PortFixedIp portFixedIp : portFixedIps) {
							srMap.put(portFixedIp.getSubnetUuid(), port.getDeviceUuid());
						}
					}
				}
				// 删除平台下旧的子网和路由关系
				routerSubnetRepository.removeByVendor(vendorId);
				// 更新子网和路由的关系
				for (Subnet subnet : subnets) {
					if (srMap.containsKey(subnet.getSubnetUuid())
							&& routerMap.containsKey(srMap.get(subnet.getSubnetUuid()))) {
						Router router = routerMap.get(srMap.get(subnet.getSubnetUuid()));
						subnet.setMenderId(userId);
						subnet.setRouterId(router.getId());
						subnet.setVpcUuid(router.getRouterUuid());
						subnetRepository.update(subnet);
						// 保存子网路由关系
						RouterSubnet routerSubnet = new RouterSubnet(router.getId(), subnet.getId(), vendorId);
						routerSubnetRepository.save(routerSubnet);
					} else {
						subnetRepository.remove(subnet.getId(), userId);
					}
				}
				// cmdb同步路由器
				// 同步安全组
				logger.info("Starting sync security group......");
				this.syncSecurityGroup(model.getGroupModels(), vendorId, userId);
				logger.info("End sync security group......");
				// 同步宿主机
				logger.info("Starting sync host......");
				this.syncHost(model.getHostModels(), vendorId, userId);
				logger.info("End sync host......");
				List<Server> servers = serverRepository.listByVendor(vendorId);
				Map<String, Server> hostMap = new HashMap<>();
				for (Server server : servers) {
					hostMap.put(server.getHostname(), server);
				}
				// 同步虚拟机
				logger.info("Starting sync server......");
				Map<String, CloudServer> serverMap = new HashMap<>();
				this.syncServer(model.getServerModels(), vendorId, userId, vendor.getType(), serverMap, hostMap);
				logger.info("End sync server......");
				// 同步镜像
				logger.info("Starting sync image......");
				this.syncImage(model.getImageModels(), vendorId, userId, vendor.getType());
				// 获取镜像信息
				Map<String, Image> imageMap = Maps.newHashMap();
				List<Image> images = imageRepository.listByVendorId(vendorId);
				for (Image image : images) {
					imageMap.put(image.getImageUuid(), image);
				}
				logger.info("End sync image......");
				// 同步云硬盘类型
				logger.info("Starting sync volume type......");
				this.syncVolumeType(model.getVolumeTypeModels(), vendorId, userId);
				// 获取云硬盘类型信息
				Map<String, VolumeType> volumeTypeMap = Maps.newHashMap();
				List<VolumeType> volumeTypes = volumeTypeRepository.listByVendorId(vendorId);
				for (VolumeType volumeType : volumeTypes) {
					volumeTypeMap.put(volumeType.getName(), volumeType);
				}
				logger.info("End sync volume type......");
				// 同步云硬盘
				logger.info("Starting sync volume......");
				this.syncVolume(model.getVolumeModels(), vendorId, userId, serverMap, imageMap, volumeTypeMap);
				logger.info("End sync volume......");
				// 获取云硬盘信息
				Map<String, Long> volumeMap = Maps.newHashMap();
				List<Volume> volumes = volumeRepository.listByVendorId(vendorId);
				for (Volume volume : volumes) {
					volumeMap.put(volume.getVolumeUuid(), volume.getId());
				}
				// 同步快照
				logger.info("Starting sync snapshot......");
				this.syncSnapshot(model.getSnapshotModels(), vendorId, userId, volumeMap, serverMap);
				logger.info("End sync snapshot......");
				// 同步浮动ip
				logger.info("Starting sync floatingIp......");
				this.syncFloatingIp(model.getFloatingIpModels(), vendorId, userId, networkMap, portMap, routerMap);
				logger.info("End sync floatingIp...");

				// 同步防火墙策略
				logger.info("Starting sync firewall policy......");
				this.syncFirewallPolicy(model.getFirewallPolicyModels(), vendor, userId);
				logger.info("End sync firewall policy......");
				// 获取防火墙策略信息
				List<FirewallPolicy> policies = firewallPolicyRepository.listByVid(vendorId);
				Map<String, Long> policyMap = Maps.newHashMap();
				for (FirewallPolicy policy : policies) {
					policyMap.put(policy.getPolicyUuid(), policy.getId());
				}
				// 同步防火墙
				logger.info("Starting sync firewall......");
				this.syncFirewall(model.getFirewallModels(), vendorId, userId, policyMap, routerMap);
				logger.info("End sync firewall......");
				// 同步防火墙规则
				logger.info("Starting sync firewall rule......");
				this.syncFirewallRule(model.getFirewallRuleModels(), vendor, userId);
				logger.info("End sync firewall rule......");
				// 同步浮动ip
				logger.info("Starting sync floatingIp......");
				this.syncFloatingIp(model.getFloatingIpModels(), vendorId, userId, networkMap, portMap, routerMap);
				logger.info("End sync floatingIp...");
				// 同步vdc
				logger.info("Starting sync vdc......");
				this.syncVdc(model.getVdcModels(), vendorId);
				logger.info("End sync vdc...");
				// 同步存储池
				logger.info("Starting sync storage pool......");
				this.syncStoragePool(model.getStorageModels(), vendorId, userId);
				logger.info("End sync  storage pool......");
			}
			// 删除IP表中不存在的脏数据
			ipService.processRubbishIp(vendor.getId());
			return new BocloudResult(true, "同步ManageOne平台数据成功");
		} catch (Exception e) {
			logger.error("Sync ManageOne error:{}", e);
			return new BocloudResult(false, "同步ManageOne平台数据失败");
		}
	}

	private void syncStoragePool(List<StorageModel> storageModels, Long vendorId, Long userId) {
		if (ListTool.isEmpty(storageModels)) {
			storageRepository.removeByVendor(vendorId);
			return;
		}
		List<Storage> storages = storageRepository.listByVendor(vendorId);
		Map<String, Storage> storageMap = Maps.newHashMap();
		for (Storage storage : storages) {
			if (storageMap.containsKey(storage.getStorageUuid())) {
				storageRepository.remove(storage.getId());
			} else {
				storageMap.put(storage.getStorageUuid(), storage);
			}
		}
		for (StorageModel storageModel : storageModels) {
			Storage storage = new Storage();
			if (storageMap.containsKey(storageModel.getStorageUuid())) {
				storage = storageMap.get(storageModel.getStorageUuid());
				BeanUtils.copyProperties(storageModel, storage);
				storage.setVendorId(vendorId);
				storage.setMenderId(userId);
				storageRepository.update(storage);
				storageMap.remove(storageModel.getStorageUuid());
				continue;
			}
			BeanUtils.copyProperties(storageModel, storage);
			storage.setVendorId(vendorId);
			storage.setMenderId(userId);
			storage.setCreatorId(userId);
			storageRepository.save(storage);
			storageMap.remove(storageModel.getStorageUuid());
		}
		for (Map.Entry<String, Storage> entry : storageMap.entrySet()) {
			Storage storage = entry.getValue();
			storageRepository.remove(storage.getId());
		}

	}

	@SuppressWarnings("unused")
	private void syncVpc(List<VpcModel> vpcModels, Long vendorId, Long userId, Map<String, Long> networkMap) {
		if (ListTool.isEmpty(vpcModels)) {
			vpcRepository.deleteByVid(vendorId, userId);
			return;
		}
		List<Vpc> vpcs = vpcRepository.list(vendorId, null);
		Map<String, Vpc> vpcMap = Maps.newHashMap();
		for (Vpc vpc : vpcs) {
			if (vpcMap.containsKey(vpc.getVpcId())) {
				vpcRepository.delete(vpc.getId(), userId);
			} else {
				vpcMap.put(vpc.getVpcId(), vpc);
			}
		}
		for (VpcModel model : vpcModels) {
			Long networkId = null;
			if (!StringUtils.isEmpty(model.getNetworkUuid())) {
				networkId = networkMap.get(model.getNetworkUuid());
			}
			Vpc vpc = new Vpc();
			if (vpcMap.containsKey(model.getVpcId())) {
				vpc = vpcMap.get(model.getVpcId());
				BeanUtils.copyProperties(model, vpc);
				vpc.setVendorId(vendorId);
				vpc.setMenderId(userId);
				vpc.setNetworkId(networkId);
				vpcRepository.update(vpc);
				vpcMap.remove(model.getVpcId());
				continue;
			}
			BeanUtils.copyProperties(model, vpc);
			vpc.preSave(userId, userId, vendorId, networkId, 0L, 0L);
			vpcRepository.save(vpc);
			vpcMap.remove(model.getVpcId());
		}
		for (Map.Entry<String, Vpc> entry : vpcMap.entrySet()) {
			Vpc vpc = entry.getValue();
			routerRepository.remove(vpc.getId(), userId);
		}

	}

	/**
	 * 同步manage one下vdc
	 * 
	 * @param models
	 * @param vendorId
	 * @throws Exception
	 */
	private void syncVdc(List<VdcModel> models, Long vendorId) throws Exception {
		if (ListTool.isEmpty(models)) {
			vdcRepository.removeByVendorId(vendorId);
			projectRepository.removeByVendorId(vendorId);
			return;
		}
		List<ManageOneVdc> vdcs = vdcRepository.listByVendorId(vendorId);
		Map<String, ManageOneVdc> vdcMap = Maps.newConcurrentMap();
		for (ManageOneVdc vdc : vdcs) {
			if (vdcMap.containsKey(vdc.getVdcId())) {
				vdcRepository.remove(vdc.getId());
			} else {
				vdcMap.put(vdc.getVdcId(), vdc);
			}
		}
		Map<String, ManageOneVdc> newVdcMap = Maps.newConcurrentMap();
		for (VdcModel model : models) {
			ManageOneVdc vdc = new ManageOneVdc();
			if (vdcMap.containsKey(model.getVdcId())) {
				vdc = vdcMap.get(model.getVdcId());
				BeanUtils.copyProperties(model, vdc);
				vdcRepository.update(vdc);
				this.syncVdcProject(model.getProjectModels(), vendorId, vdc.getId());
				vdcMap.remove(model.getVdcId());
				newVdcMap.put(vdc.getVdcId(), vdc);
				continue;
			}
			BeanUtils.copyProperties(model, vdc);
			vdc.setVendorId(vendorId);
			vdcRepository.save(vdc);
			this.syncVdcProject(model.getProjectModels(), vendorId, vdc.getId());
			vdcMap.remove(model.getVdcId());
			newVdcMap.put(vdc.getVdcId(), vdc);
		}
		for (Map.Entry<String, ManageOneVdc> set : vdcMap.entrySet()) {
			vdcRepository.remove(set.getValue().getId());
			projectRepository.removeByVdcId(set.getValue().getId());
		}
		// 设置parentId
		vdcs = vdcRepository.listByVendorId(vendorId);
		List<ManageOneVdc> updateVdcs = new ArrayList<>();
		for (ManageOneVdc vdc : vdcs) {
			ManageOneVdc parent = newVdcMap.get(vdc.getUpperVdcId());
			if (null != parent) {
				vdc.setParentId(parent.getId());
			} else {
				vdc.setParentId(0L);
			}
			updateVdcs.add(vdc);
		}
		if (!ListTool.isEmpty(updateVdcs)) {
			vdcRepository.batchUpdate(updateVdcs, 1000);
		}
	}

	/**
	 * 同步vdc下项目
	 * 
	 * @param models
	 * @param vendorId
	 * @param vdcId
	 * @throws Exception
	 */
	private void syncVdcProject(List<VdcProjectModel> models, Long vendorId, Long vdcId) throws Exception {
		if (ListTool.isEmpty(models)) {
			projectRepository.removeByVdcId(vdcId);
			return;
		}
		List<ManageOneProject> projects = projectRepository.listByVdcId(vdcId);
		Map<String, ManageOneProject> projectMap = Maps.newConcurrentMap();
		for (ManageOneProject project : projects) {
			if (projectMap.containsKey(project.getProjectId())) {
				projectRepository.remove(project.getId());
			} else {
				projectMap.put(project.getProjectId(), project);
			}
		}
		for (VdcProjectModel model : models) {
			ManageOneProject project = new ManageOneProject();
			if (projectMap.containsKey(model.getProjectId())) {
				project = projectMap.get(model.getProjectId());
				BeanUtils.copyProperties(model, project);
				projectRepository.update(project);
				projectMap.remove(model.getProjectId());
				continue;
			}
			BeanUtils.copyProperties(model, project);
			project.setVendorId(vendorId);
			project.setVdcId(vdcId);
			projectRepository.save(project);
			projectMap.remove(model.getProjectId());
		}
		for (Map.Entry<String, ManageOneProject> set : projectMap.entrySet()) {
			projectRepository.remove(set.getValue().getId());
		}
	}

	private void syncFirewallRule(List<FirewallRuleModel> models, CloudVendor vendor, Long userId) throws Exception {
		if (ListTool.isEmpty(models)) {
			firewallRuleRepository.removeByVid(vendor.getId(), userId);
			return;
		}
		List<FirewallRule> rules = firewallRuleRepository.listByVid(vendor.getId());
		Map<String, FirewallRule> ruleMap = Maps.newHashMap();
		for (FirewallRule rule : rules) {
			if (ruleMap.containsKey(rule.getRuleUuid())) {
				firewallRuleRepository.remove(rule.getId(), userId);
			} else {
				ruleMap.put(rule.getRuleUuid(), rule);
			}
		}
		// 重置防火墙策略与规则的绑定
		firewallRuleRepository.resetPolicyByVendor(vendor.getId());
		for (FirewallRuleModel model : models) {
			FirewallRule rule = new FirewallRule();
			if (ruleMap.containsKey(model.getRuleUuid())) {
				rule = ruleMap.get(model.getRuleUuid());
				BeanUtils.copyProperties(model, rule);
				rule.setVendorId(vendor.getId());
				rule.setMenderId(userId);
				FirewallPolicy firewallPolicy = firewallPolicyRepository.queryByPolicyUuid(model.getPolicyUuid(),
						vendor.getId());
				if (null != firewallPolicy) {
					rule.setPolicyId(firewallPolicy.getId());
				} else {
					rule.setPolicyId(null);
					rule.setPolicyUuid(null);
				}
				Firewall firewall = firewallRepository.queryByPolicyUuid(model.getPolicyUuid(), vendor.getId());
				if (null != firewall) {
					rule.setFirewallId(firewall.getId());
					rule.setFirewallUuid(firewall.getFirewallUuid());
				} else {
					rule.setFirewallId(null);
					rule.setFirewallUuid(null);
				}
				rule.setVendorType(vendor.getType());
				firewallRuleRepository.update(rule);
				ruleMap.remove(model.getRuleUuid());
				continue;
			}
			BeanUtils.copyProperties(model, rule);
			rule.preSave(userId, userId, vendor.getId(), 0L, 0L);
			FirewallPolicy firewallPolicy = firewallPolicyRepository.queryByPolicyUuid(model.getPolicyUuid(),
					vendor.getId());
			if (null != firewallPolicy) {
				rule.setPolicyId(firewallPolicy.getId());
			}
			Firewall firewall = firewallRepository.queryByPolicyUuid(model.getPolicyUuid(), vendor.getId());
			if (null != firewall) {
				rule.setFirewallId(firewall.getId());
				rule.setFirewallUuid(firewall.getFirewallUuid());
			}
			rule.setVendorType(vendor.getType());
			firewallRuleRepository.save(rule);
			ruleMap.remove(model.getRuleUuid());
		}
		for (Entry<String, FirewallRule> entry : ruleMap.entrySet()) {
			firewallRuleRepository.remove(entry.getValue().getId(), userId);
		}

	}

	private void syncFirewall(List<FirewallModel> models, Long vendorId, Long userId, Map<String, Long> policyMap,
			Map<String, Router> routerMap) throws Exception {
		if (ListTool.isEmpty(models)) {
			firewallRepository.removeByVid(vendorId, userId);
			return;
		}
		List<Firewall> firewalls = firewallRepository.listByVid(vendorId);
		Map<String, Firewall> firewallMap = Maps.newHashMap();
		for (Firewall firewall : firewalls) {
			if (firewallMap.containsKey(firewall.getFirewallUuid())) {
				firewallRepository.remove(firewall.getId(), userId);
			} else {
				firewallMap.put(firewall.getFirewallUuid(), firewall);
			}
		}
		// 重置云平台路由与防火墙绑定状态
		routerRepository.resetFirewallByVendor(vendorId);
		for (FirewallModel model : models) {
			Firewall firewall = new Firewall();
			List<String> routerUuids = model.getRouterUuids();
			if (firewallMap.containsKey(model.getFirewallUuid())) {
				firewall = firewallMap.get(model.getFirewallUuid());
				BeanUtils.copyProperties(model, firewall);
				firewall.setMenderId(userId);
				if (StringUtils.isEmpty(model.getPolicyUuid())) {
					firewall.setPolicyId(null);
					firewall.setPolicyUuid(null);
				} else {
					firewall.setPolicyId(policyMap.get(model.getPolicyUuid()));
				}
				firewallRepository.update(firewall);
				if (!ListTool.isEmpty(routerUuids)) {
					// 更新防火墙绑定路由
					for (String routerUuid : routerUuids) {
						// 更新防火墙与路由的绑定
						Router router = routerMap.get(routerUuid);
						if (null != router) {
							routerRepository.updateFirewallByRouterId(router.getId(), firewall.getId(),
									firewall.getFirewallUuid());
						}
					}
				}
				firewallMap.remove(model.getFirewallUuid());
				continue;
			}
			BeanUtils.copyProperties(model, firewall);
			firewall.preSave(userId, userId, vendorId, 0L, 0L);
			if (!StringUtils.isEmpty(model.getPolicyUuid())) {
				firewall.setPolicyId(policyMap.get(model.getPolicyUuid()));
			}
			firewallRepository.save(firewall);
			if (!ListTool.isEmpty(routerUuids)) {
				// 更新防火墙绑定路由
				for (String routerUuid : routerUuids) {
					// 更新防火墙与路由的绑定
					Router router = routerMap.get(routerUuid);
					if (null != router) {
						routerRepository.updateFirewallByRouterId(router.getId(), firewall.getId(),
								firewall.getFirewallUuid());
					}
				}
			}
		}
		for (Entry<String, Firewall> entry : firewallMap.entrySet()) {
			firewallRepository.remove(entry.getValue().getId(), userId);
		}

	}

	private void syncFirewallPolicy(List<FirewallPolicyModel> models, CloudVendor vendor, Long userId)
			throws Exception {
		if (ListTool.isEmpty(models)) {
			firewallPolicyRepository.removeByVid(vendor.getId(), userId);
			return;
		}
		List<FirewallPolicy> policys = firewallPolicyRepository.listByVid(vendor.getId());
		Map<String, FirewallPolicy> policyMap = Maps.newHashMap();
		for (FirewallPolicy policy : policys) {
			if (policyMap.containsKey(policy.getPolicyUuid())) {
				firewallPolicyRepository.remove(policy.getId(), userId);
			} else {
				policyMap.put(policy.getPolicyUuid(), policy);
			}
		}
		for (FirewallPolicyModel model : models) {
			FirewallPolicy firewallPolicy = new FirewallPolicy();
			if (policyMap.containsKey(model.getPolicyUuid())) {
				firewallPolicy = policyMap.get(model.getPolicyUuid());
				BeanUtils.copyProperties(model, firewallPolicy);
				firewallPolicy.setMenderId(userId);
				firewallPolicy.setVendorType(vendor.getType());
				firewallPolicyRepository.update(firewallPolicy);
				policyMap.remove(model.getPolicyUuid());
				continue;
			}
			BeanUtils.copyProperties(model, firewallPolicy);
			firewallPolicy.preSave(userId, userId, vendor.getId(), 0L, 0L);
			firewallPolicy.setVendorType(vendor.getType());
			firewallPolicyRepository.save(firewallPolicy);
			policyMap.remove(model.getPolicyUuid());
		}
		for (Entry<String, FirewallPolicy> entry : policyMap.entrySet()) {
			firewallPolicyRepository.remove(entry.getValue().getId(), userId);
		}
	}

	private void syncHost(List<HostModel> hostModels, Long vendorId, Long userId) throws Exception {
		if (ListTool.isEmpty(hostModels)) {
			List<Server> hosts = serverRepository.listByVendor(vendorId);
			for (Server server : hosts) {
				serverConfigRepository.removeBySid(server.getId());
			}
			serverRepository.removeByVendor(vendorId, userId);
			return;
		}
		List<Server> hosts = serverRepository.listByVendor(vendorId);
		Map<String, Server> serverMap = Maps.newHashMap();
		for (Server server : hosts) {
			if (serverMap.containsKey(server.getUuid())) {
				serverConfigRepository.removeBySid(server.getId());
				serverRepository.remove(server.getId(), userId);
			} else {
				serverMap.put(server.getUuid(), server);
			}
		}
		for (HostModel hostModel : hostModels) {
			Server server = null;
			if (serverMap.containsKey(hostModel.getUuid())) {
				server = serverMap.get(hostModel.getUuid());
				server.setName(hostModel.getName());
				server.setUuid(hostModel.getUuid());
				server.setManageIp(hostModel.getHostIp());
				server.setHostname(hostModel.getHostName());
				server.setCategory(hostModel.getCategory());
				server.setCreatorId(userId);
				server.setMenderId(userId);
				server.setGmtModify(new Date());
				// server.setStatus(hostModel.getStatus());
				// server.setPowerState(hostModel.getPowerState());
				if ("up".equalsIgnoreCase(hostModel.getPowerState())) {
					server.setPowerState(BocloudStatus.Server.RUNNING.name());
				} else if ("down".equalsIgnoreCase(hostModel.getPowerState())) {
					server.setPowerState(BocloudStatus.Server.STOPPED.name());
				}
				if ("enabled".equalsIgnoreCase(hostModel.getStatus())) {
					server.setStatus(BocloudStatus.Basic.ENABLED.name());
				} else if ("disabled".equalsIgnoreCase(hostModel.getStatus())) {
					server.setStatus(BocloudStatus.Basic.DISABLED.name());
				}
				server.setCpuModel(hostModel.getCpuModel());
				server.setModelName(hostModel.getModelName());
				server.setVendorId(vendorId);
				serverRepository.update(server);
				ServerConfig serverConfig = serverConfigRepository.getBySid(server.getId());
				serverConfig.setCpuHz(hostModel.getCpuTotal());
				serverConfig.setCpuUsed(hostModel.getCpuUsed());
				serverConfig.setMemoryCapacity(hostModel.getMemTotal());
				serverConfig.setMemUsed(hostModel.getMemUsed());
				serverConfig.setDiskCapacity(hostModel.getDiskTotal());
				serverConfig.setDiskUsed(hostModel.getDiskUsed());
				serverConfigRepository.update(serverConfig);
				serverMap.remove(hostModel.getUuid());
				continue;
			}
			server = new Server();
			server.setName(hostModel.getName());
			server.setUuid(hostModel.getUuid());
			server.setManageIp(hostModel.getHostIp());
			server.setHostname(hostModel.getHostName());
			server.setCategory(hostModel.getCategory());
			// server.setStatus(hostModel.getStatus());
			// server.setPowerState(hostModel.getPowerState());
			if ("up".equalsIgnoreCase(hostModel.getPowerState())) {
				server.setPowerState(BocloudStatus.Server.RUNNING.name());
			} else if ("down".equalsIgnoreCase(hostModel.getPowerState())) {
				server.setPowerState(BocloudStatus.Server.STOPPED.name());
			}
			if ("enabled".equalsIgnoreCase(hostModel.getStatus())) {
				server.setStatus(BocloudStatus.Basic.ENABLED.name());
			} else if ("disabled".equalsIgnoreCase(hostModel.getStatus())) {
				server.setStatus(BocloudStatus.Basic.DISABLED.name());
			}
			server.setCreatorId(userId);
			server.setMenderId(userId);
			server.setVendorId(vendorId);
			server.setCpuModel(hostModel.getCpuModel());
			server.setModelName(hostModel.getModelName());
			serverRepository.save(server);
			ServerConfig serverConfig = new ServerConfig();
			serverConfig.setServerId(server.getId());
			serverConfig.setCpuHz(hostModel.getCpuTotal());
			serverConfig.setCpuUsed(hostModel.getCpuUsed());
			serverConfig.setMemoryCapacity(hostModel.getMemTotal());
			serverConfig.setMemUsed(hostModel.getMemUsed());
			serverConfig.setDiskCapacity(hostModel.getDiskTotal());
			serverConfig.setDiskUsed(hostModel.getDiskUsed());
			serverConfigRepository.save(serverConfig);
		}
		for (Map.Entry<String, Server> entry : serverMap.entrySet()) {
			Long serverId = entry.getValue().getId();
			serverRepository.remove(serverId, userId);
			serverConfigRepository.removeBySid(serverId);
		}
	}

	/**
	 * 同步安全组和规则
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncSecurityGroup(List<SecurityGroupModel> models, Long vendorId, Long userId) throws Exception {
		// 当安全组为空时，清空数据库
		if (ListTool.isEmpty(models)) {
			List<SecurityGroup> groups = securityGroupRepository.listByVendorId(vendorId);
			for (SecurityGroup group : groups) {
				serverSgroupRepository.removeBySgid(group.getId());
			}
			securityGroupRuleRepository.removeByVid(vendorId, userId);
			securityGroupRepository.removeByVid(vendorId, userId);
			return;
		}
		List<SecurityGroup> groups = securityGroupRepository.listByVendorId(vendorId);
		Map<String, SecurityGroup> groupMap = Maps.newHashMap();
		for (SecurityGroup group : groups) {
			if (groupMap.containsKey(group.getGroupUuid())) {
				securityGroupRepository.remove(group.getId(), userId);
			} else {
				groupMap.put(group.getGroupUuid(), group);
			}
		}
		for (SecurityGroupModel model : models) {
			boolean flag = true;
			Long groupId = null;
			// 更新存在的安全组
			if (groupMap.containsKey(model.getGroupUuid())) {
				flag = false;
				SecurityGroup group = groupMap.get(model.getGroupUuid());
				if (null != group.getRemark()) {
					if (!group.getName().equals(model.getName()) || !group.getRemark().equals(model.getRemark())) {
						group.setName(model.getName());
						group.setRemark(model.getRemark());
						group.setMenderId(userId);
						group.setVendorId(vendorId);
						securityGroupRepository.update(group);
					}
				} else {
					if (!group.getName().equals(model.getName())) {
						group.setName(model.getName());
						group.setRemark(model.getRemark());
						group.setMenderId(userId);
						group.setVendorId(vendorId);
						securityGroupRepository.update(group);
					}
				}
				groupId = group.getId();
				groupMap.remove(model.getGroupUuid());
			}
			// 保存新的安全组
			if (flag) {
				SecurityGroup group = JSONObject.parseObject(JSONObject.toJSONString(model), SecurityGroup.class);
				group.preSave(userId, userId, vendorId, 0L, 0L);
				securityGroupRepository.save(group);
				groupId = group.getId();
			}
			this.syncSecurityGroupRule(model.getModels(), vendorId, userId, groupId);
		}
		// 删除不存在的安全组
		for (Map.Entry<String, SecurityGroup> entry : groupMap.entrySet()) {
			Long sgId = entry.getValue().getId();
			serverSgroupRepository.removeBySgid(sgId);
			securityGroupRuleRepository.removeBySgId(sgId, userId);
			securityGroupRepository.remove(sgId, userId);
		}

	}

	/**
	 * 同步安全组规则
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @param groupId
	 * @throws Exception
	 */
	private void syncSecurityGroupRule(List<SecurityGroupRuleModel> models, Long vendorId, Long userId, Long groupId)
			throws Exception {
		List<SecurityGroupRule> rules = securityGroupRuleRepository.listBySgId(groupId);
		Map<String, SecurityGroupRule> ruleMap = Maps.newHashMap();
		for (SecurityGroupRule rule : rules) {
			if (ruleMap.containsKey(rule.getRuleUuid())) {
				securityGroupRuleRepository.remove(rule.getId(), userId);
			} else {
				ruleMap.put(rule.getRuleUuid(), rule);
			}
		}
		for (SecurityGroupRuleModel model : models) {
			if (ruleMap.containsKey(model.getRuleUuid())) {
				SecurityGroupRule rule = ruleMap.get(model.getRuleUuid());
				rule.setGmtModify(new Date());
				rule.setMenderId(1L);
				rule.setEtherType(model.getEtherType());
				rule.setProtocol(model.getProtocol());
				securityGroupRuleRepository.update(rule);
				ruleMap.remove(model.getRuleUuid());
				continue;
			}
			// 保存新的安全组规则
			SecurityGroupRule rule = JSONObject.parseObject(JSONObject.toJSONString(model), SecurityGroupRule.class);
			rule.preSave(userId, userId, vendorId, groupId, 0L, 0L);
			securityGroupRuleRepository.save(rule);
		}
		// 删除不存在的安全组规则
		for (Map.Entry<String, SecurityGroupRule> entry : ruleMap.entrySet()) {
			securityGroupRuleRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步所属域
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncRegions(List<RegionModel> models, Long vendorId, Long userId) throws Exception {
		if (ListTool.isEmpty(models)) {
			regionRepository.deleteByVid(vendorId);
			return;
		}
		List<Region> regions = regionRepository.list(vendorId);
		Map<String, Region> mapRegion = new HashMap<String, Region>();
		for (Region region : regions) {
			if (mapRegion.containsKey(region.getName())) {
				regionRepository.delete(region.getId());
			} else {
				mapRegion.put(region.getName(), region);
			}
		}
		for (RegionModel model : models) {
			Region reg = new Region();
			if (mapRegion.containsKey(model.getName())) {
				reg = mapRegion.get(model.getName());
				reg.setVendorId(vendorId);
				BeanUtils.copyProperties(model, reg);
				regionRepository.update(reg);
				mapRegion.remove(model.getName());
			} else {
				BeanUtils.copyProperties(model, reg);
				reg.setVendorId(vendorId);
				regionRepository.save(reg);
				mapRegion.remove(model.getName());
			}
		}
		for (String keyset : mapRegion.keySet()) {
			regionRepository.delete(mapRegion.get(keyset).getId());
		}
	}

	/**
	 * 同步虚拟机
	 *
	 * @param serverModels
	 * @param vendorId
	 * @param userId
	 * @param type
	 * @param serverMap
	 * @throws Exception
	 */
	private void syncServer(List<ServerModel> serverModels, Long vendorId, Long userId, String type,
			Map<String, CloudServer> serverMap, Map<String, Server> hostMap) throws Exception {
		if (ListTool.isEmpty(serverModels)) {
			List<CloudServer> servers = cloudServerRepository.listByVendorId(vendorId);
			for (CloudServer server : servers) {
				serverSgroupRepository.removeBySid(server.getId());
				volumeRepository.detachVolumes(server.getId(), userId);
				serverLabelRepository.deleteByTarget(server.getId(), "VM");
			}
			cloudServerRepository.removeByVid(vendorId, userId);
			return;
		}
		// 获取平台虚拟机信息
		List<CloudServer> servers = cloudServerRepository.listByVendorId(vendorId);
		Map<String, CloudServer> cloudSeverMap = Maps.newHashMap();
		for (CloudServer server : servers) {
			if (BocloudStatus.Server.BUILDING.name().equals(server.getStatus())) {
				continue;
			}
			cloudSeverMap.put(server.getInstanceId(), server);
		}
		// 获取平台安全组信息
		List<SecurityGroup> securityGroups = securityGroupRepository.listByVendorId(vendorId);
		Map<String, Long> groupMap = Maps.newHashMap();
		for (SecurityGroup group : securityGroups) {
			groupMap.put(group.getName(), group.getId());
		}
		for (ServerModel server : serverModels) {
			CloudServer vm = new CloudServer();
			Flavor flavor = flavorRepository.getByFlavorUuid(server.getFlavorUuid());
			boolean flag = true;
			// 设置内网IP
			List<NetworkBean> networkBeans = Lists.newArrayList();
			// key networkUuid
			Map<String, List<Port>> portMap = Maps.newHashMap();
			String privateIps = "";
			String routerUuid = "";
			List<Port> ports = portRepository.listByDeviceId(server.getInstanceId(), vendorId);
			if (null != ports) {
				for (Port port : ports) {
					port.setPortFixedIps(portFixedIpRepository.listByPortUuid(port.getPortUuid()));
					if (portMap.containsKey(port.getNetworkUuid())) {
						List<Port> list = portMap.get(port.getNetworkUuid());
						list.add(port);
					} else {
						List<Port> list = Lists.newArrayList();
						list.add(port);
						portMap.put(port.getNetworkUuid(), list);
					}
				}
				for (String key : portMap.keySet()) {
					List<Port> portList = portMap.get(key);
					if (portList.isEmpty()) {
						continue;
					}
					Network network = networkRepository.getByNetId(key);
					if (null == network) {
						continue;
					}
					NetworkBean networkBean = new NetworkBean(network.getId(), network.getName(),
							network.getNetworkUuid());
					List<AddressBean> addresses = Lists.newArrayList();
					for (Port port : portList) {
						List<PortFixedIp> portFixedIps = port.getPortFixedIps();
						if (ListTool.isEmpty(portFixedIps)) {
							continue;
						}
						for (PortFixedIp portFixedIp : portFixedIps) {
							Subnet subnet = subnetRepository.getBySubId(portFixedIp.getSubnetUuid());
							if (null == subnet) {
								continue;
							}
							routerUuid = subnet.getVpcUuid();
							AddressBean address = new AddressBean(subnet.getId(), subnet.getName(), network.getId(),
									subnet.getSubnetUuid(), port.getId(), port.getPortUuid(),
									portFixedIp.getIpAddress());
							addresses.add(address);
						}
					}
					networkBean.setAddresses(addresses);
					if (!addresses.isEmpty()) {
						networkBeans.add(networkBean);
					}
				}
				if (networkBeans.isEmpty()) {
					privateIps = null;
				} else {
					privateIps = JSONObject.toJSONString(networkBeans);
				}
			}
			// 更新已创建的虚拟机
			if (cloudSeverMap.containsKey(server.getInstanceId())) {
				flag = false;
				vm = cloudSeverMap.get(server.getInstanceId());
				server.setOsCategory(vm.getOsCategory());
				server.setOsName(vm.getOsName());
				server.setOsVersion(vm.getOsVersion());
				String account = vm.getAccount();
				if (StringUtils.isEmpty(account)) {
					Image image = imageRepository.getByImageUuid(server.getImageUuid());
					if (null != image) {
						account = image.getDefaultUser();
					}
				}
				server.setAccount(account);
				server.setPassword(vm.getPassword());
				BeanUtils.copyProperties(server, vm);
				if ("error".equalsIgnoreCase(server.getStatus())) {
					vm.setStatus(BocloudStatus.Server.EXCEPTION.name());
				} else {
					vm.setStatus(server.getStatus());
				}
				vm.setPassword(server.getPassword());
				vm.setMenderId(userId);
				vm.setIsTemplate(false);
				vm.setGmtVmCreate(server.getGmtVmCreate());
				vm.setPrivateIps(privateIps);
				if (null != flavor) {
					vm.setCpu(flavor.getCpu());
					vm.setMemory(flavor.getMemory());
				}
				vm.setRegion(server.getZone());
				vm.setRegionId(server.getZone());
				vm.setRouterUuid(routerUuid);
				Server host = hostMap.get(server.getHostName());
				if (null != host) {
					vm.setCpuModel(host.getCpuModel());
					vm.setModelName(host.getModelName());
					vm.setHostId(host.getId());
				}
				cloudServerRepository.update(vm);
				cloudSeverMap.remove(vm.getInstanceId());
				// 更新资源表
				Resource resource = serverOperationHelper.syncOsVResource(vendorId, vm, userId);
				vm.setResource(resource);
			}
			if (flag) {
				BeanUtils.copyProperties(server, vm);
				if ("error".equalsIgnoreCase(server.getStatus())) {
					vm.setStatus(BocloudStatus.Server.EXCEPTION.name());
				} else {
					vm.setStatus(server.getStatus());
				}
				vm.setIsTemplate(false);
				vm.setResourceId(IDFactory.instance().uuid());
				vm.setVendorType(type);
				vm.setGmtVmCreate(server.getGmtVmCreate());
				vm.setPrivateIps(privateIps);
				vm.setRecycle(false);
				vm.preSave(userId, userId, vendorId, 0L, null, null, 0L, 0L);
				if (StringUtils.isEmpty(vm.getOsCategory())) {
					vm.setOsCategory(OSCategory.LINUX.name());
				}
				String account = vm.getAccount();
				if (StringUtils.isEmpty(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());
				}
				vm.setRegion(server.getZone());
				vm.setRegionId(server.getZone());
				vm.setRouterUuid(routerUuid);
				Server host = hostMap.get(server.getHostName());
				if (null != host) {
					vm.setCpuModel(host.getCpuModel());
					vm.setModelName(host.getModelName());
					vm.setHostId(host.getId());
				}
				cloudServerRepository.save(vm);
				// 更新资源表
				Resource resource = serverOperationHelper.syncOsVResource(vendorId, vm, userId);
				vm.setResource(resource);
			}
			serverMap.put(server.getInstanceId(), vm);
			// 同步存虚拟机和安全组关系
			if (ListTool.isEmpty(server.getSecurityGroups())) {
				serverSgroupRepository.removeBySid(vm.getId());
				continue;
			}
			List<ServerSgroup> sgroups = serverSgroupRepository.listByServerId(vm.getId());
			Map<Long, Long> sgroupMap = Maps.newHashMap();
			for (ServerSgroup sgroup : sgroups) {
				sgroupMap.put(sgroup.getGroupId(), sgroup.getServerId());
			}
			List<String> groups = server.getSecurityGroups();
			for (String group : groups) {
				if (sgroupMap.containsKey(groupMap.get(group))) {
					sgroupMap.remove(groupMap.get(group));
					continue;
				}
				// 保存虚拟机和安全组关系
				serverSgroupRepository.save(new ServerSgroup(vm.getId(), groupMap.get(group)));
			}
			// 删除不存在的虚拟机和安全组关系
			for (Map.Entry<Long, Long> entry : sgroupMap.entrySet()) {
				serverSgroupRepository.remove(entry.getKey(), entry.getValue());
			}
		}
		for (Map.Entry<String, CloudServer> entry : cloudSeverMap.entrySet()) {
			CloudServer server = entry.getValue();
			resourceRepository.remove(server.getId(), ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
					userId);
			volumeRepository.detachVolumes(server.getId(), userId);
			serverSgroupRepository.removeBySid(server.getId());
			cloudServerRepository.remove(server.getId(), userId);
			serverLabelRepository.deleteByTarget(server.getId(), "VM");
		}
	}

	/**
	 * 同步网络
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncNetwork(List<NetworkModel> models, Long vendorId, Long userId) throws Exception {
		if (ListTool.isEmpty(models)) {
			List<Network> networks = networkRepository.listByVid(vendorId);
			for (Network network : networks) {
				List<Subnet> subnets = subnetRepository.listByNetwork(network.getId());
				for (Subnet subnet : subnets) {
					routerSubnetRepository.deleteBySubnet(subnet.getId());
					ipRepository.deleteBySubnetId(subnet.getId(), vendorId);
					ipPoolRepository.removeBySubnetId(subnet.getId(), vendorId, userId);
				}
				List<Port> ports = portRepository.listByNetworkUuid(network.getNetworkUuid(), vendorId);
				for (Port port : ports) {
					portFixedIpRepository.deleteByPortId(port.getId());
				}
			}
			portRepository.removeByVid(vendorId, userId);
			subnetRepository.removeByVid(vendorId, userId);
			tenantNetworkRepository.deleteByVendor(vendorId);
			networkRepository.removeByVid(vendorId, userId);
			return;
		}
		List<Network> networks = networkRepository.listByVid(vendorId);
		Map<String, Network> netMap = Maps.newHashMap();
		for (Network network : networks) {
			if (netMap.containsKey(network.getNetworkUuid())) {
				networkRepository.remove(network.getId(), userId);
			} else {
				netMap.put(network.getNetworkUuid(), network);
			}
		}
		for (NetworkModel model : models) {
			Long networkId = null;
			if (netMap.containsKey(model.getNetworkUuid())) {
				Network network = netMap.get(model.getNetworkUuid());
				BeanUtils.copyProperties(model, network);
				network.setMenderId(userId);
				networkRepository.update(network);
				netMap.remove(model.getNetworkUuid());
				networkId = network.getId();
			} else {
				Network network = JSONObject.parseObject(JSONObject.toJSONString(model), Network.class);
				network.preSave(userId, userId, vendorId, null);
				networkRepository.save(network);
				networkId = network.getId();
			}
			this.syncSubnet(model.getSubnets(), vendorId, userId, networkId);
		}
		// 存在异常网络数据
		for (Map.Entry<String, Network> entry : netMap.entrySet()) {
			// 设置虚拟机异常
			List<CloudServer> list = cloudServerRepository.list(vendorId, entry.getValue().getNetworkUuid());
			for (CloudServer vm : list) {
				vm.setStatus(BocloudStatus.Server.EXCEPTION.name());
				cloudServerRepository.update(vm);
			}
			Network network = entry.getValue();
			List<Subnet> subnets = subnetRepository.listByNetwork(network.getId());
			for (Subnet subnet : subnets) {
				ipPoolRepository.removeBySubnetId(subnet.getId(), vendorId, userId);
				routerSubnetRepository.deleteBySubnet(subnet.getId());
			}
			List<Port> ports = portRepository.listByNetworkUuid(network.getNetworkUuid(), vendorId);
			for (Port port : ports) {
				portFixedIpRepository.deleteByPortId(port.getId());
			}
			Long networkId = network.getId();
			// 删除端口
			portRepository.removeByNetworkId(networkId, userId);
			// 刪除IP
			ipRepository.deleteByNetworkId(networkId);
			// 删除子网
			subnetRepository.removeByNetworkId(networkId, userId);
			// 删除租户授权网络信息
			tenantNetworkRepository.deleteByNetworkId(networkId);
			// 删除网络
			networkRepository.remove(networkId, userId);
		}
	}

	/**
	 * 同步子网
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @param networkId
	 * @throws Exception
	 */
	private void syncSubnet(List<SubnetModel> models, Long vendorId, Long userId, Long networkId) throws Exception {
		if (ListTool.isEmpty(models)) {
			List<Subnet> subnets = subnetRepository.listByNetwork(networkId);
			for (Subnet subnet : subnets) {
				routerSubnetRepository.deleteBySubnet(subnet.getId());
				ipPoolRepository.removeBySubnetId(subnet.getId(), vendorId, userId);
				List<Port> ports = portRepository.listBySubnetUuid(subnet.getNetworkUuid());
				for (Port port : ports) {
					portFixedIpRepository.deleteByPortId(port.getId());
				}
			}
			ipRepository.deleteByNetworkId(networkId);
			portRepository.removeByNetworkId(networkId, userId);
			subnetRepository.removeByNetworkId(networkId, userId);
			return;
		}
		// 处理子网
		List<Subnet> subnets = subnetRepository.list(vendorId, networkId);
		Map<String, Subnet> subMap = Maps.newHashMap();
		for (Subnet subnet : subnets) {
			if (subMap.containsKey(subnet.getSubnetUuid())) {
				subnetRepository.remove(subnet.getId(), userId);
			} else {
				subMap.put(subnet.getSubnetUuid(), subnet);
			}
		}
		// 重置网络和子网关系
		subnetRepository.resetNetwork(vendorId, networkId);
		for (SubnetModel model : models) {
			if (subMap.containsKey(model.getSubnetUuid())) {
				Subnet subnet = subMap.get(model.getSubnetUuid());
				BeanUtils.copyProperties(model, subnet);
				subnet.setMenderId(userId);
				subnet.setNetworkId(networkId);
				subnetRepository.update(subnet);
				syncIpPool(subnet, false, vendorId, userId, networkId);
				subMap.remove(model.getSubnetUuid());
				continue;
			}
			Subnet subnet = new Subnet();
			BeanUtils.copyProperties(model, subnet);
			subnet.preSave(userId, userId, vendorId, networkId);
			subnetRepository.save(subnet);
			syncIpPool(subnet, true, vendorId, userId, networkId);
		}
		// 存在异常子网数据
		for (Map.Entry<String, Subnet> entry : subMap.entrySet()) {
			Subnet subnet = entry.getValue();
			ipRepository.deleteBySubnetId(subnet.getId(), vendorId);
			ipPoolRepository.removeBySubnetId(subnet.getId(), vendorId, userId);
			List<Port> ports = portRepository.listBySubnetUuid(subnet.getNetworkUuid());
			for (Port port : ports) {
				portFixedIpRepository.deleteByPortId(port.getId());
			}
			portRepository.removeBySubnetId(subnet.getId(), userId);
			routerSubnetRepository.deleteBySubnet(subnet.getId());
			subnetRepository.remove(subnet.getId(), userId);
		}
	}

	/**
	 * 同步IP池
	 *
	 * @param subnet
	 * @param isNew
	 * @param vendorId
	 * @param userId
	 * @param networkId
	 * @throws Exception
	 */
	public void syncIpPool(Subnet subnet, boolean isNew, Long vendorId, Long userId, Long networkId) throws Exception {
		if (isNew) {
			IpPool pool = new IpPool(subnet.getGateway(), subnet.getCidr(), subnet.getIpPools(), subnet.getDnsNames(),
					subnet.getId(), networkId, vendorId);
			pool.setMenderId(userId);
			pool.setCreatorId(userId);
			pool.setVersion("V" + subnet.getIpVersion());
			pool.setName(subnet.getName());
			ipPoolRepository.save(pool);
			return;
		}
		IpPool pool = ipPoolRepository.queryBySubnet(subnet.getId(), vendorId);
		if (null == pool) {
			pool = new IpPool(subnet.getGateway(), subnet.getCidr(), subnet.getIpPools(), subnet.getDnsNames(),
					subnet.getId(), networkId, vendorId);
			pool.setMenderId(userId);
			pool.setCreatorId(userId);
			pool.setVersion("V" + subnet.getIpVersion());
			ipPoolRepository.save(pool);
			return;
		}
		pool.setCidr(subnet.getCidr());
		pool.setGateway(subnet.getGateway());
		pool.setPools(subnet.getIpPools());
		pool.setDnsNames(subnet.getDnsNames());
		pool.setVersion("V" + subnet.getIpVersion());
		pool.setMenderId(userId);
		pool.setName(subnet.getName());
		ipPoolRepository.update(pool);
	}

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

	/**
	 * 同步云硬盘类型
	 *
	 * @param volumeTypeModels
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncVolumeType(List<VolumeTypeModel> volumeTypeModels, Long vendorId, Long userId) throws Exception {
		if (ListTool.isEmpty(volumeTypeModels)) {
			volumeTypeRepository.deleteByVendorId(vendorId);
			return;
		}
		List<VolumeType> volumeTypes = volumeTypeRepository.listByVendorId(vendorId);
		Map<String, VolumeType> volumeTypeMap = Maps.newHashMap();
		for (VolumeType volumeType : volumeTypes) {
			if (volumeTypeMap.containsKey(volumeType.getVolumeTypeUuid())) {
				volumeTypeRepository.remove(volumeType.getId());
			} else {
				volumeTypeMap.put(volumeType.getVolumeTypeUuid(), volumeType);
			}
		}
		for (VolumeTypeModel volumeTypeModel : volumeTypeModels) {
			boolean flag = true;
			if (volumeTypeMap.containsKey(volumeTypeModel.getVolumeTypeUuid())) {
				flag = false;
				VolumeType volumeType = volumeTypeMap.get(volumeTypeModel.getVolumeTypeUuid());
				BeanUtils.copyProperties(volumeTypeModel, volumeType);
				volumeTypeRepository.update(volumeType);
				volumeTypeMap.remove(volumeTypeModel.getVolumeTypeUuid());
			}
			if (flag) {// 保存块设备
				VolumeType volumeType = new VolumeType();
				BeanUtils.copyProperties(volumeTypeModel, volumeType);
				volumeType.setVendorId(vendorId);
				volumeTypeRepository.save(volumeType);
			}
		}
		// 删除异常数据
		for (Map.Entry<String, VolumeType> entry : volumeTypeMap.entrySet()) {
			volumeTypeRepository.remove(entry.getValue().getId());
		}
	}

	/**
	 * 同步云硬盘
	 *
	 * @param volumeModels
	 * @param vendorId
	 * @param userId
	 * @param serverMap
	 * @param imageMap
	 * @throws Exception
	 */
	private void syncVolume(List<VolumeModel> volumeModels, Long vendorId, Long userId,
			Map<String, CloudServer> serverMap, Map<String, Image> imageMap, Map<String, VolumeType> volumeTypeMap)
			throws Exception {
		if (ListTool.isEmpty(volumeModels)) {
			volumeRepository.removeByVid(vendorId, userId);
			return;
		}
		List<Volume> volumes = volumeRepository.listByVendorId(vendorId);
		Map<String, Volume> volumeMap = Maps.newHashMap();
		for (Volume volume : volumes) {
			if (volumeMap.containsKey(volume.getVolumeUuid())) {
				volumeRepository.remove(volume.getId(), userId);
			} else {
				volumeMap.put(volume.getVolumeUuid(), volume);
			}
		}
		for (VolumeModel volumeModel : volumeModels) {
			boolean flag = true;
			if (volumeMap.containsKey(volumeModel.getVolumeUuid())) {
				flag = false;
				Volume volume = volumeMap.get(volumeModel.getVolumeUuid());
				long id = volume.getId();
				BeanUtils.copyProperties(volumeModel, volume);
				volume.setId(id);
				volume.setMenderId(userId);
				volume.setStatus(volumeModel.getStatus().toUpperCase());
				volume.setCreateTime(volumeModel.getCreateTime());
				// 同步云硬盘和虚拟机之间的挂载关系
				List<ServerVolumeModel> models = volumeModel.getModels();
				if (ListTool.isEmpty(models)) {
					volume.setServerId(null);
					volume.setDevice(null);
				} else {
					updateOsCategory(models, serverMap, imageMap, volume, userId);
				}
				volumeRepository.update(volume);
				volumeMap.remove(volumeModel.getVolumeUuid());
			}
			if (flag) {// 保存块设备
				Volume volume = JSONObject.parseObject(JSONObject.toJSONString(volumeModel), Volume.class);
				if (StringUtils.isEmpty(volume.getName())) {
					volume.setName(volume.getVolumeUuid());
				}
				volume.setStatus(volume.getStatus().toUpperCase());
				volume.setCreateTime(volumeModel.getCreateTime());
				volume.preSave(userId, userId, 0L, vendorId, 0L);
				// 同步块设备和虚拟机之间的挂载关系
				List<ServerVolumeModel> models = volumeModel.getModels();
				if (!ListTool.isEmpty(models)) {
					updateOsCategory(models, serverMap, imageMap, volume, userId);
				}
				// 设定云硬盘类型
				if (volumeTypeMap.containsKey(volumeModel.getVolumeType())) {
					VolumeType volumeType = volumeTypeMap.get(volumeModel.getVolumeType());
					volume.setVolumeTypeId(volumeType.getId());
					volume.setVolumeType(volumeType.getName());
					volume.setVolumeTypeName(volumeType.getName());
				}
				volumeRepository.save(volume);
			}
		}
		// 删除异常数据
		for (Map.Entry<String, Volume> entry : volumeMap.entrySet()) {
			volumeRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步虚拟机操作系统类别
	 *
	 * @param models
	 * @param serverMap
	 * @param imageMap
	 * @param volume
	 * @param userId
	 * @throws Exception
	 */
	private void updateOsCategory(List<ServerVolumeModel> models, Map<String, CloudServer> serverMap,
			Map<String, Image> imageMap, Volume volume, Long userId) throws Exception {
		ServerVolumeModel model = models.get(0);
		String device = model.getDevice();
		CloudServer server = serverMap.get(model.getInstanceId());
		if (null == server) {
			return;
		}
		// 挂载路径为/vda的是虚拟机的根磁盘
		if (null != device && (device.contains("/vda") || device.contains("/sda"))) {
			if (null != server) {
				server.setMenderId(userId);
				server.setDisk(volume.getSize());
			}
			Image image = imageMap.get(volume.getImageUuid());
			if (null != image && null != image.getOsCategory() && null != server) {
				Resource resource = server.getResource();
				String osCategory = image.getOsCategory().toLowerCase();
				if ("linux".contains(osCategory)) {
					osCategory = OSCategory.LINUX.name();
				} else if ("windows".contains(osCategory)) {
					osCategory = OSCategory.WINDOWS.name();
				} else if ("unix".contains(osCategory)) {
					osCategory = OSCategory.UNIX.name();
				} else if ("aix".contains(osCategory)) {
					osCategory = OSCategory.AIX.name();
				}
				if (!osCategory.equals(server.getOsCategory())) {
					server.setOsCategory(osCategory);
					server.setOsName(image.getOsCategory());
					server.setOsVersion(image.getOsVersion());
					resource.setOsCategory(osCategory);
					resourceRepository.update(resource);
				}
			}
			cloudServerRepository.update(server);
		}
		if (null != server) {
			volume.setServerId(server.getId());
		}
		volume.setDevice(device);
	}

	/**
	 * 同步镜像
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @param type
	 * @throws Exception
	 */
	private void syncImage(List<ImageModel> models, Long vendorId, Long userId, String type) throws Exception {
		if (ListTool.isEmpty(models)) {
			imageRepository.removeByVid(vendorId, userId);
			return;
		}
		List<Image> images = imageRepository.listByVendorId(vendorId);
		Map<String, Image> imagesMap = Maps.newConcurrentMap();
		for (Image image : images) {
			if (imagesMap.containsKey(image.getImageUuid())) {
				imageRepository.remove(image.getId(), userId);
			} else {
				imagesMap.put(image.getImageUuid(), 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());
					model.setOsCategory(image.getOsCategory());
					model.setOsName(image.getOsName());
					model.setOsVersion(image.getOsVersion());
					model.setRemark(image.getRemark());
					BeanUtils.copyProperties(model, image);
					image.setMenderId(userId);
					image.setVendorType(type);
					image.setDefaultUser(model.getDefaultUser());
					imageRepository.update(image);
					imagesMap.remove(model.getImageUuid());
					continue;
				}
				BeanUtils.copyProperties(model, image);
				image.setVendorId(vendorId);
				image.setCreatorId(userId);
				image.setVendorType(type);
				image.setMenderId(userId);
				image.setTenantId(0L);
				if (!StringUtils.isEmpty(image.getOsCategory())) {
					image.setOsCategory(image.getOsCategory().toUpperCase());
				}
				image.setCatalog("VM");
				imageRepository.save(image);
				imagesMap.remove(image.getImageUuid());
			}
		}
		for (Map.Entry<String, Image> set : imagesMap.entrySet()) {
			imageRepository.remove(set.getValue().getId(), userId);
		}
	}

	/**
	 * 同步规格
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncFlavor(List<FlavorModel> models, Long vendorId, Long userId) throws Exception {
		if (ListTool.isEmpty(models)) {
			flavorRepository.removeByVid(vendorId);
			return;
		}
		List<Flavor> flavors = flavorRepository.listByVendorId(vendorId);
		List<Flavor> resultData = Lists.newArrayList();
		resultData.addAll(flavors);
		for (FlavorModel model : models) {
			boolean flag = true;
			for (Flavor flavor : flavors) {
				if (flavor.getFlavorUuid().equals(model.getFlavorUuid())) {
					flag = false;
					BeanUtils.copyProperties(model, flavor);
					flavorRepository.update(flavor);
					resultData.remove(flavor);
				}
			}
			if (flag) {
				Flavor flavor = JSONObject.parseObject(JSONObject.toJSONString(model), Flavor.class);
				flavor.setVendorId(vendorId);
				flavorRepository.save(flavor);
			}
		}
		// 存在异常数据
		for (Flavor flavor : resultData) {
			// 设置虚拟机异常
			List<CloudServer> list = cloudServerRepository.listByFid(vendorId, flavor.getFlavorUuid());
			for (CloudServer vm : list) {
				vm.setStatus(BocloudStatus.Server.EXCEPTION.name());
				cloudServerRepository.update(vm);
			}
			// 删除配置
			flavorRepository.delete(flavor.getId());
		}
	}

	/**
	 * 保存端口信息
	 *
	 * @param portModels
	 * @param vendorId
	 * @param userId
	 * @param networkMap
	 * @param subnetMap
	 * @throws Exception
	 */
	private void syncPort(List<PortModel> portModels, Long vendorId, Long userId, Map<String, Long> networkMap,
			Map<String, Long> subnetMap) throws Exception {
		if (ListTool.isEmpty(portModels)) {
			List<Port> ports = portRepository.listByVid(vendorId);
			for (Port port : ports) {
				List<PortFixedIp> fixedIps = portFixedIpRepository.listByPortId(port.getId());
				for (PortFixedIp fixedIp : fixedIps) {
					ipRepository.delete(fixedIp.getIpAddress(), fixedIp.getId(), vendorId);
				}
				portFixedIpRepository.deleteByPortId(port.getId());
			}
			portRepository.removeByVid(vendorId, userId);
			return;
		}
		List<Port> ports = portRepository.listByVid(vendorId);
		savePort(portModels, vendorId, userId, networkMap, subnetMap, ports);
	}

	/**
	 * 保存端口信息
	 *
	 * @param newPortModels
	 * @param vendorId
	 * @param userId
	 * @param networkMap
	 * @param subnetMap
	 * @param oldPorts
	 * @throws Exception
	 */
	private void savePort(List<PortModel> newPortModels, Long vendorId, Long userId, Map<String, Long> networkMap,
			Map<String, Long> subnetMap, List<Port> oldPorts) throws Exception {
		Map<String, Port> portsMap = Maps.newConcurrentMap();
		for (Port port : oldPorts) {
			if (null != port.getPortUuid() && portsMap.containsKey(port.getPortUuid())) {
				List<PortFixedIp> fixedIps = portFixedIpRepository.listByPortId(port.getId());
				for (PortFixedIp fixedIp : fixedIps) {
					ipRepository.delete(fixedIp.getIpAddress(), fixedIp.getId(), vendorId);
				}
				portFixedIpRepository.deleteByPortId(port.getId());
				portRepository.remove(port.getId(), userId);
			} else if (null != port.getPortUuid()) {
				portsMap.put(port.getPortUuid(), port);
			}
		}
		for (PortModel portModel : newPortModels) {
			Port port = new Port();
			boolean flag = true;
			if (null != portModel.getPortUuid()) {
				if (portsMap.containsKey(portModel.getPortUuid())) {
					flag = false;
					port = portsMap.get(portModel.getPortUuid());
					BeanUtils.copyProperties(portModel, port);
					port.setVendorId(vendorId);
					port.setMenderId(userId);
					portRepository.update(port);
					batchSavePortFixedIp(portModel.getPortFixedIps(), port.getPortUuid(), port.getId(), vendorId);
					portsMap.remove(portModel.getPortUuid());
				}
				if (flag) {
					if (networkMap.containsKey(portModel.getNetworkUuid())) {
						BeanUtils.copyProperties(portModel, port);
						port.preSave(userId, userId, vendorId, networkMap.get(portModel.getNetworkUuid()));
						portRepository.save(port);
						batchSavePortFixedIp(portModel.getPortFixedIps(), port.getPortUuid(), port.getId(), vendorId);
					}
				}
			}
		}
		for (Map.Entry<String, Port> set : portsMap.entrySet()) {
			Port port = set.getValue();
			List<PortFixedIp> fixedIps = portFixedIpRepository.listByPortId(port.getId());
			for (PortFixedIp fixedIp : fixedIps) {
				ipRepository.delete(fixedIp.getIpAddress(), fixedIp.getSubnetId(), vendorId);
			}
			portFixedIpRepository.deleteByPortId(port.getId());
			portRepository.remove(port.getId(), userId);
		}
	}

	/**
	 * 同步某个网络下的端口
	 *
	 * @param portModels
	 * @param vendorId
	 * @param userId
	 * @param tenantId
	 * @param network
	 * @throws Exception
	 */
	public void syncPort4Network(List<PortModel> portModels, Long vendorId, Long userId, Long tenantId, Network network)
			throws Exception {
		if (ListTool.isEmpty(portModels)) {
			List<Port> ports = portRepository.listByNetworkUuid(network.getNetworkUuid(), vendorId);
			for (Port port : ports) {
				List<PortFixedIp> fixedIps = portFixedIpRepository.listByPortId(port.getId());
				for (PortFixedIp fixedIp : fixedIps) {
					ipRepository.delete(fixedIp.getIpAddress(), fixedIp.getId(), vendorId);
				}
				portFixedIpRepository.deleteByPortId(port.getId());
			}
			portRepository.removeByNetworkId(network.getId(), userId);
			return;
		}
		// 加载网络下所有的子网信息
		List<Subnet> subnetlist = subnetRepository.listByNetworkUuid(network.getNetworkUuid(), vendorId);
		Map<String, Long> subnetMap = new HashMap<>();
		if (!ListTool.isEmpty(subnetlist)) {
			for (Subnet subnet : subnetlist) {
				subnetMap.put(subnet.getSubnetUuid(), subnet.getId());
			}
		}
		List<Port> oldPorts = portRepository.listByNetworkUuid(network.getNetworkUuid(), vendorId);
		Map<String, Port> portsMap = Maps.newConcurrentMap();
		for (Port port : oldPorts) {
			if (portsMap.containsKey(port.getPortUuid())) {
				List<PortFixedIp> fixedIps = portFixedIpRepository.listByPortId(port.getId());
				for (PortFixedIp fixedIp : fixedIps) {
					ipRepository.delete(fixedIp.getIpAddress(), fixedIp.getId(), vendorId);
				}
				portFixedIpRepository.deleteByPortId(port.getId());
				portRepository.remove(port.getId(), userId);
			} else {
				portsMap.put(port.getPortUuid(), port);
			}
		}
		for (PortModel portModel : portModels) {
			Port port = new Port();
			boolean flag = true;
			if (portsMap.containsKey(portModel.getPortUuid())) {
				flag = false;
				port = portsMap.get(portModel.getPortUuid());
				BeanUtils.copyProperties(portModel, port);
				port.setMenderId(userId);
				portRepository.update(port);
				batchSavePortFixedIp(portModel.getPortFixedIps(), port.getPortUuid(), port.getId(), vendorId);
				portsMap.remove(portModel.getPortUuid());
			}
			if (flag) {
				BeanUtils.copyProperties(portModel, port);
				port.preSave(userId, userId, vendorId, network.getId());
				portRepository.save(port);
				batchSavePortFixedIp(portModel.getPortFixedIps(), port.getPortUuid(), port.getId(), vendorId);
			}

		}
		for (Map.Entry<String, Port> entry : portsMap.entrySet()) {
			Port port = entry.getValue();
			List<PortFixedIp> fixedIps = portFixedIpRepository.listByPortId(port.getId());
			for (PortFixedIp fixedIp : fixedIps) {
				ipRepository.delete(fixedIp.getIpAddress(), fixedIp.getId(), vendorId);
			}
			portFixedIpRepository.deleteByPortId(port.getId());
			portRepository.remove(port.getId(), userId);
		}
	}

	/**
	 * 同步路由
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @param networkMap
	 * @throws Exception
	 */
	private void syncRouter(List<RouterModel> models, Long vendorId, Long userId, Map<String, Long> networkMap)
			throws Exception {
		if (ListTool.isEmpty(models)) {
			List<Router> routers = routerRepository.listByVid(vendorId);
			for (Router router : routers) {
				routerSubnetRepository.deleteByRouter(router.getId());
				vpcRepository.deleteByRouterId(router.getId(), vendorId, userId);
			}
			routerRepository.removeByVid(vendorId, userId);
			return;
		}
		List<Router> routers = routerRepository.listByVid(vendorId);
		Map<String, Router> routesMap = Maps.newHashMap();
		for (Router router : routers) {
			if (routesMap.containsKey(router.getRouterUuid())) {
				routerRepository.remove(router.getId(), userId);
				routerSubnetRepository.deleteByRouter(router.getId());
				vpcRepository.deleteByRouterId(router.getId(), vendorId, userId);
			} else {
				routesMap.put(router.getRouterUuid(), router);
			}
		}
		//
		List<Vpc> vpcs = vpcRepository.list(vendorId, null);
		Map<String, Vpc> vpcMap = Maps.newHashMap();
		for (Vpc vpc : vpcs) {
			if (vpcMap.containsKey(vpc.getVpcId())) {
				vpcRepository.delete(vpc.getId(), userId);
			} else {
				vpcMap.put(vpc.getVpcId(), vpc);
			}
		}
		for (RouterModel model : models) {
			Long networkId = null;
			if (!StringUtils.isEmpty(model.getNetworkUuid())) {
				networkId = networkMap.get(model.getNetworkUuid());
			}
			Router router = new Router();
			Vpc vpc = new Vpc();
			if (routesMap.containsKey(model.getRouterUuid())) {
				router = routesMap.get(model.getRouterUuid());
				BeanUtils.copyProperties(model, router);
				router.setVendorId(vendorId);
				router.setMenderId(userId);
				router.setNetworkId(networkId);
				routerRepository.update(router);
				routesMap.remove(model.getRouterUuid());
				// 保存vpc
				vpc = vpcMap.get(model.getRouterUuid());
				if (vpc == null) {
					vpc = new Vpc();
					// 保存vpc
					BeanUtils.copyProperties(router, vpc);
					vpc.setRouterId(router.getId());
					vpc.setVpcId(router.getRouterUuid());
					vpc.setId(null);
					vpcRepository.save(vpc);
				} else {
					Long vpcId = vpc.getId();
					BeanUtils.copyProperties(router, vpc);
					vpc.setRouterId(router.getId());
					vpc.setId(vpcId);
					vpc.setVpcId(router.getRouterUuid());
					vpcRepository.update(vpc);
				}
				vpcMap.remove(model.getRouterUuid());
				continue;
			}
			BeanUtils.copyProperties(model, router);
			router.preSave(userId, userId, vendorId, networkId, 0L, 0L);
			routerRepository.save(router);
			// 保存vpc
			vpc = vpcMap.get(model.getRouterUuid());
			if (vpc == null) {
				vpc = new Vpc();
				// 保存vpc
				BeanUtils.copyProperties(router, vpc);
				vpc.setRouterId(router.getId());
				vpc.setVpcId(router.getRouterUuid());
				vpc.setId(null);
				vpcRepository.save(vpc);
			} else {
				Long vpcId = vpc.getId();
				BeanUtils.copyProperties(router, vpc);
				vpc.setRouterId(router.getId());
				vpc.setId(vpcId);
				vpc.setVpcId(router.getRouterUuid());
				vpcRepository.update(vpc);
			}
			vpcMap.remove(model.getRouterUuid());
			routesMap.remove(model.getRouterUuid());
			vpcMap.remove(model.getRouterUuid());
		}
		for (Map.Entry<String, Router> entry : routesMap.entrySet()) {
			Router router = entry.getValue();
			routerRepository.remove(router.getId(), userId);
			vpcRepository.deleteByRouterId(router.getId(), vendorId, userId);
			routerSubnetRepository.deleteByRouter(router.getId());
		}
		for (Map.Entry<String, Vpc> entry : vpcMap.entrySet()) {
			Vpc vpc = entry.getValue();
			routerRepository.remove(vpc.getId(), userId);
		}
	}

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

	/**
	 * 同步浮动IP
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @param networkMap
	 * @param portMap
	 * @param routerMap
	 * @throws Exception
	 */
	private void syncFloatingIp(List<FloatingIpModel> models, Long vendorId, Long userId, Map<String, Long> networkMap,
			Map<String, Long> portMap, Map<String, Router> routerMap) throws Exception {
		// 当浮动IP为空时，清空数据库
		if (ListTool.isEmpty(models)) {
			floatingIpRepository.removeByVid(vendorId, userId);
			return;
		}
		// 获取浮动ip信息
		List<FloatingIp> fIps = floatingIpRepository.listByVid(vendorId);
		Map<String, FloatingIp> fIpMap = Maps.newHashMap();
		for (FloatingIp fIp : fIps) {
			if (fIpMap.containsKey(fIp.getFloatingIpUuid())) {
				floatingIpRepository.remove(fIp.getId(), userId);
			} else {
				fIpMap.put(fIp.getFloatingIpUuid(), fIp);
			}
		}
		for (FloatingIpModel model : models) {
			if (fIpMap.containsKey(model.getFloatingIpUuid())) {
				FloatingIp fIp = fIpMap.get(model.getFloatingIpUuid());
				BeanUtils.copyProperties(model, fIp);
				fIp.setMenderId(userId);
				if (StringUtils.isEmpty(model.getFixedIpAddress())) {
					fIp.setFixedIpAddress(null);
					fIp.setPortId(null);
					fIp.setPortUuid(null);
					fIp.setRouterId(null);
					fIp.setRouterUuid(null);
				} else {
					fIp.setPortId(portMap.get(fIp.getPortUuid()));
					Router router = routerMap.get(fIp.getRouterUuid());
					if (null != router) {
						fIp.setRouterId(router.getId());
					}
				}
				floatingIpRepository.update(fIp);
				fIpMap.remove(model.getFloatingIpUuid());
				continue;
			}
			FloatingIp fIp = new FloatingIp();
			BeanUtils.copyProperties(model, fIp);
			if (!StringUtils.isEmpty(fIp.getFixedIpAddress())) {
				fIp.setPortId(portMap.get(fIp.getPortUuid()));
				Router router = routerMap.get(fIp.getRouterUuid());
				if (null != router) {
					fIp.setRouterId(router.getId());
				}
			}
			fIp.preSave(userId, userId, vendorId, networkMap.get(model.getFloatingNetworkUuid()), 0L, 0L);
			floatingIpRepository.save(fIp);
		}
		// 删除不存在的浮动IP
		for (Map.Entry<String, FloatingIp> entry : fIpMap.entrySet()) {
			floatingIpRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 全更新PortFixedIp 固定IP
	 *
	 * @param models
	 * @param portUuid
	 * @param portId
	 * @param vendorId
	 * @return
	 * @throws Exception
	 */
	public boolean batchSavePortFixedIp(List<PortFixedIpModel> models, String portUuid, Long portId, Long vendorId)
			throws Exception {
		// 查出老的
		List<PortFixedIp> list = portFixedIpRepository.listByPortUuid(portUuid);
		Map<String, PortFixedIp> oldValues = new HashMap<>();
		for (PortFixedIp fixedIp : list) {
			if (oldValues.containsKey(fixedIp.getIpAddress())) {
				portFixedIpRepository.delete(fixedIp.getId());
			} else {
				oldValues.put(fixedIp.getIpAddress(), fixedIp);
			}
		}
		if (!ListTool.isEmpty(models)) {
			for (PortFixedIpModel model : models) {
				// 对象转换
				PortFixedIp fixedIp = new PortFixedIp();
				BeanUtils.copyProperties(model, fixedIp);
				if (fixedIp.getSubnetUuid() == null || fixedIp.getIpAddress() == null) {
					continue;
				}
				Subnet subnet = subnetRepository.query(fixedIp.getSubnetUuid(), vendorId);
				if (null == subnet) {
					continue;
				}
				fixedIp.setSubnetId(subnet.getId());
				if (oldValues.containsKey(fixedIp.getIpAddress())) {
					PortFixedIp portFixedIp = oldValues.get(fixedIp.getIpAddress());
					portFixedIp.setSubnetId(subnet.getId());
					portFixedIp.setPortId(portId);
					portFixedIp.setPortUuid(portUuid);
					portFixedIpRepository.update(portFixedIp);
					oldValues.remove(fixedIp.getIpAddress());
				} else {
					fixedIp.setPortId(portId);
					fixedIp.setPortUuid(portUuid);
					portFixedIpRepository.save(fixedIp);
				}
				Ip ip = ipRepository.checkExist(fixedIp.getIpAddress(), fixedIp.getSubnetId(), vendorId);
				if (null == ip) {
					String mask = IPAddress.getIPAddress(fixedIp.getIpAddress()).getMask(subnet.getCidr());
					ip = new Ip(fixedIp.getIpAddress(), mask, subnet.getGateway(), subnet.getDnsNames(), vendorId,
							IDFactory.instance().uuid(), null, IpStatus.used);
					ip.setTarget(portId);
					ip.setCatalog("PORT");
					ip.setNetworkId(subnet.getNetworkId());
					ip.setSubnetId(subnet.getId());
					IpPool pool = ipPoolRepository.queryBySubnet(subnet.getId(), vendorId);
					if (null != pool) {
						ip.setPoolId(pool.getId());
					}
					ipRepository.save(ip);
				} else {
					if (null == ip.getTarget()) {
						ip.setTarget(portId);
						ipRepository.update(ip);
					}
				}
			}
		}
		// 删除该删的
		for (Entry<String, PortFixedIp> entry : oldValues.entrySet()) {
			ipRepository.delete(entry.getValue().getIpAddress(), entry.getValue().getSubnetId(), vendorId);
			portFixedIpRepository.delete(entry.getValue().getId());
		}
		return true;
	}

}
