package com.bocloud.ims.service.transportor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.entity.enums.*;
import com.bocloud.cmp.model.*;
import com.bocloud.cmp.provider.utils.IPAddress;
import com.bocloud.common.enums.BoCloudService;
import com.bocloud.common.enums.OSCategory;
import com.bocloud.common.enums.ResourceCatalog;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.utils.IDFactory;
import com.bocloud.common.utils.ListTool;
import com.bocloud.ims.entity.VolumeType;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.Ip.IpStatus;
import com.bocloud.ims.interfaces.resource.CloudStackService;
import com.bocloud.ims.interfaces.resource.IpService;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.service.internal.CosInternalService;
import com.bocloud.ims.service.model.cmdb.CmdbInfo;
import com.bocloud.ims.service.model.cmdb.CmdbModel;
import com.bocloud.ims.service.model.cmdb.CmdbRelation;
import com.bocloud.ims.service.topology.InstanceMessageDispatcher;
import com.bocloud.ims.service.utils.CmdbInfoConvertor;
import com.bocloud.ims.service.utils.ListUtils;
import com.bocloud.ims.service.utils.ServerOperationHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;

import java.util.*;
import java.util.Map.Entry;

public class OpenstackTransportor {

	private static Logger logger = LoggerFactory.getLogger(OpenstackTransportor.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 PortRepository portRepository;
	private RouterRepository routerRepository;
	private ServerRepository serverRepository;
	private ServerConfigRepository serverConfigRepository;
	private ServerAssetsRepository serverAssetsRepository;
	private ResourceRepository resourceRepository;
	private IpRepository ipRepository;
	private SecurityGroupRepository securityGroupRepository;
	private SecurityGroupRuleRepository securityGroupRuleRepository;
	private ServerSgroupRepository serverSgroupRepository;
	private FirewallRepository firewallRepository;
	private FirewallPolicyRepository firewallPolicyRepository;
	private FirewallRuleRepository firewallRuleRepository;
	private FloatingIpRepository floatingIpRepository;
	private LoadBalancerRepository loadBalancerRepository;
	private LbListenerRepository lbListenerRepository;
	private LbMemberRepository lbMemberRepository;
	private LbPoolRepository lbPoolRepository;
	private HealthMonitorRepository healthMonitorRepository;
	private PortFixedIpRepository portFixedIpRepository;
	private KeypairRepository keypairRepository;
	private TenantNetworkRepository tenantNetworkRepository;
	private ObjectRelationRepository objectRelationRepository;
	private RouterSubnetRepository routerSubnetRepository;
	private AmqpTemplate amqpTemplate;
	private ServerOperationHelper serverOperationHelper;
	private IpPoolRepository ipPoolRepository;
	private ClusterRepository clusterRepository;
	private ServerLabelRepository serverLabelRepository;
	private IpService ipService;
	private VolumeTypeRepository volumeTypeRepository;
	private QosPolicyRepository qosPolicyRepository;
	private QosPolicyRulesRepository qosPolicyRulesRepository;
	private OSTenantRepository osTenantRepository;
	private ClusterNodeRepository clusterNodeRepository;
	private CloudStackRepository cloudStackRepository;
	private CloudStackService cloudStackService;
	private StackTemplateVersionRepository stackTemplateVersionRepository;
	private VpnRepository vpnRepository;
	private VpnPolicyRepository vpnPolicyRepository;
	private VpnConnRepository vpnConnRepository;
	private AutoScalingRepository autoScalingRepository;
	private VpcRepository vpcRepository;
	private InstanceMessageDispatcher messageDispatcher;

	public OpenstackTransportor() {
		super();
	}

	public OpenstackTransportor(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;
	}

	public OpenstackTransportor(IpRepository ipRepository, IpPoolRepository ipPoolRepository,
			SubnetRepository subnetRepository, PortFixedIpRepository portFixedIpRepository) {
		super();
		this.ipRepository = ipRepository;
		this.ipPoolRepository = ipPoolRepository;
		this.subnetRepository = subnetRepository;
		this.portFixedIpRepository = portFixedIpRepository;
	}

	public OpenstackTransportor(RegionRepository regionRepository, CloudServerRepository cloudServerRepository,
			ServerRepository serverRepository, NetworkRepository networkRepository, SubnetRepository subnetRepository,
			VolumeRepository volumeRepository, SnapshotRepository snapshotRepository, ImageRepository imageRepository,
			FlavorRepository flavorRepository, PortRepository portRepository, RouterRepository routerRepository,
			ServerConfigRepository serverConfigRepository, ServerAssetsRepository serverAssetsRepository,
			ResourceRepository resourceRepository, IpRepository ipRepository,
			SecurityGroupRepository securityGroupRepository, SecurityGroupRuleRepository securityGroupRuleRepository,
			ServerSgroupRepository serverSgroupRepository, FirewallRepository firewallRepository,
			FirewallPolicyRepository firewallPolicyRepository, FirewallRuleRepository firewallRuleRepository,
			FloatingIpRepository floatingIpRepository, LoadBalancerRepository loadBalancerRepository,
			LbListenerRepository lbListenerRepository, LbMemberRepository lbMemberRepository,
			LbPoolRepository lbPoolRepository, HealthMonitorRepository healthMonitorRepository,
			ObjectStorageContainerRepository objectStorageContainerRepository,
			ObjectStorageItemRepository objectStorageItemRepository, PortFixedIpRepository portFixedIpRepository,
			KeypairRepository keypairRepository, TenantNetworkRepository tenantNetworkRepository,
			ObjectRelationRepository objectRelationRepository, RouterSubnetRepository routerSubnetRepository,
			CosInternalService cosInternalService, AmqpTemplate amqpTemplate,
			ServerOperationHelper serverOperationHelper, IpPoolRepository ipPoolRepository,
			ClusterRepository clusterRepository, ServerLabelRepository serverLabelRepository, IpService ipService,
			VolumeTypeRepository volumeTypeRepository, QosPolicyRepository qosPolicyRepository,
			QosPolicyRulesRepository qosPolicyRulesRepository, OSTenantRepository osTenantRepository,
			ClusterNodeRepository clusterNodeRepository, CloudStackRepository cloudStackRepository,
			StackTemplateVersionRepository stackTemplateVersionRepository, VpnRepository vpnRepository,
			VpnPolicyRepository vpnPolicyRepository, VpnConnRepository vpnConnRepository,
			CloudStackService cloudStackService, AutoScalingRepository autoScalingRepository,
			VpcRepository vpcRepository, InstanceMessageDispatcher messageDispatcher) {
		super();
		this.cloudStackRepository = cloudStackRepository;
		this.autoScalingRepository = autoScalingRepository;
		this.cloudStackService = cloudStackService;
		this.stackTemplateVersionRepository = stackTemplateVersionRepository;
		this.clusterNodeRepository = clusterNodeRepository;
		this.qosPolicyRepository = qosPolicyRepository;
		this.qosPolicyRulesRepository = qosPolicyRulesRepository;
		this.regionRepository = regionRepository;
		this.cloudServerRepository = cloudServerRepository;
		this.networkRepository = networkRepository;
		this.snapshotRepository = snapshotRepository;
		this.imageRepository = imageRepository;
		this.flavorRepository = flavorRepository;
		this.subnetRepository = subnetRepository;
		this.volumeRepository = volumeRepository;
		this.portRepository = portRepository;
		this.routerRepository = routerRepository;
		this.serverRepository = serverRepository;
		this.serverConfigRepository = serverConfigRepository;
		this.serverAssetsRepository = serverAssetsRepository;
		this.resourceRepository = resourceRepository;
		this.ipRepository = ipRepository;
		this.securityGroupRepository = securityGroupRepository;
		this.securityGroupRuleRepository = securityGroupRuleRepository;
		this.serverSgroupRepository = serverSgroupRepository;
		this.firewallRepository = firewallRepository;
		this.firewallPolicyRepository = firewallPolicyRepository;
		this.firewallRuleRepository = firewallRuleRepository;
		this.floatingIpRepository = floatingIpRepository;
		this.loadBalancerRepository = loadBalancerRepository;
		this.lbListenerRepository = lbListenerRepository;
		this.lbMemberRepository = lbMemberRepository;
		this.lbPoolRepository = lbPoolRepository;
		this.healthMonitorRepository = healthMonitorRepository;
		this.portFixedIpRepository = portFixedIpRepository;
		this.keypairRepository = keypairRepository;
		this.tenantNetworkRepository = tenantNetworkRepository;
		this.objectRelationRepository = objectRelationRepository;
		this.routerSubnetRepository = routerSubnetRepository;
		this.amqpTemplate = amqpTemplate;
		this.serverOperationHelper = serverOperationHelper;
		this.ipPoolRepository = ipPoolRepository;
		this.clusterRepository = clusterRepository;
		this.serverLabelRepository = serverLabelRepository;
		this.ipService = ipService;
		this.volumeTypeRepository = volumeTypeRepository;
		this.osTenantRepository = osTenantRepository;
		this.vpnRepository = vpnRepository;
		this.vpnPolicyRepository = vpnPolicyRepository;
		this.vpnConnRepository = vpnConnRepository;
		this.vpcRepository = vpcRepository;
		this.messageDispatcher = messageDispatcher;
	}

	public BocloudResult sync(CloudVendor vendor, Object data, Long userId) {
		CmdbModel cmdbModel = new CmdbModel();
		cmdbModel.setUuid(IDFactory.instance().uuid());
		cmdbModel.setServiceName(BoCloudService.IMS.name());
		cmdbModel.setManagerId(userId);
		List<CmdbInfo> infos = Lists.newArrayList();
		// 添加云平台数据
		infos.add(CmdbInfoConvertor.getInfo(vendor, null, null, CloudProvider.OPENSTACK));
		try {
			if (null != data) {
				Long vendorId = vendor.getId();
				if (cloudServerRepository.hasBuilding(vendorId)) {
					return new BocloudResult(false, "该平台下有虚拟机正在创建，请稍后进行同步操作");
				}
				if (autoScalingRepository.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);
				OSSyncModel model = JSONObject.parseObject(content, OSSyncModel.class);
				// 同步OpenStack租户
				logger.info("Starting sync openstack tenant......");
				this.syncOsTenant(model.getTenants(), vendorId, userId);
				logger.info("End sync openstack tenant......");
				// 同步可用区域
				logger.info("Starting sync zone......");
				this.syncRegion(model.getRegions(), vendorId, userId);
				logger.info("End sync zone......");
				// 同步宿主机
				logger.info("Starting sync host......");
				Map<String, Server> hostMap = new HashMap<>();
				this.syncHost(model.getHostModels(), vendorId, userId, hostMap, infos);
				logger.info("End sync host......");
				// 同步stack
				logger.info("Starting sync stack......");
				this.syncCloudStack(model.getStackModels(), vendorId, userId);
				logger.info("End sync stack......");
				// 同步stack version
				logger.info("Starting sync stack version......");
				this.syncStackTemplateVersion(model.getStackVersionModels(), vendorId, userId);
				logger.info("End sync stack version......");
				// 同步HostResource
				logger.info("Starting sync HostResource......");
				this.syncHostResource(model.getHostResourcesModels(), vendorId, userId);
				logger.info("End sync HostResource......");
				// 同步主机聚合
				logger.info("Starting host aggregate zone......");
				Map<Long, Cluster> clusterMap = new HashMap<>();
				this.syncHostAggregate(model.getClusterModels(), vendorId, userId, infos, vendor.getGuid(), clusterMap);
				logger.info("End sync host aggregate......");
				List<Server> servers = serverRepository.listByVendor(vendorId);
				for (Server server : servers) {
					ServerConfig config = serverConfigRepository.getBySid(server.getId());
					if (null == config) {
						continue;
					}
					// 宿主机与对象的关系
					List<CmdbRelation> relations = Lists.newArrayList();
					Long clusterId = server.getClusterId();
					if (null == clusterId || 0L == clusterId) {
						relations.add(
								new CmdbRelation(ModuleCode.OS_VENDOR.name(), 1L, ListUtils.getList(vendor.getGuid())));
					} else {
						Cluster cluster = clusterMap.get(clusterId);
						if (null == cluster) {
							continue;
						}
						relations.add(new CmdbRelation(ModuleCode.OS_HOST_GROUP.name(), 1L,
								ListUtils.getList(cluster.getGuid())));
					}
					// cmdb更新宿主机数据
					infos.add(CmdbInfoConvertor.getInfo(server, config, null, relations, CloudProvider.OPENSTACK));
				}
				// 同步网络
				logger.info("Starting sync network......");
				this.syncNetwork(model.getNetworkModels(), vendorId, userId, infos, vendor.getGuid());
				logger.info("End sync network......");
				// 获取平台网络信息
				Map<String, Network> networkMap = Maps.newHashMap();
				List<Network> networks = networkRepository.listByVid(vendorId);
				for (Network network : networks) {
					networkMap.put(network.getNetworkUuid(), network);
				}
				// 获取平台网络子网信息
				Map<String, Subnet> subnetMap = Maps.newHashMap();
				List<Subnet> subnets = subnetRepository.listByVid(vendorId);
				for (Subnet subnet : subnets) {
					subnetMap.put(subnet.getSubnetUuid(), subnet);
				}
				// 同步端口
				logger.info("Starting sync port......");
				this.syncPort(model.getPortModels(), vendorId, userId, networkMap, subnetMap, infos);
				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());
				}
				// 同步路由
				logger.info("Starting sync router......");
				this.syncRouter(model.getRouterModels(), vendorId, userId, networkMap, infos);
				logger.info("End sync router......");
				// 获取平台路由信息
				Map<String, Long> routerMap = Maps.newHashMap();
				List<Router> routers = routerRepository.listByVid(vendorId);
				for (Router router : routers) {
					routerMap.put(router.getRouterUuid(), router.getId());
				}
				// 获取子网和路由的关系
				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()))) {
						subnet.setMenderId(userId);
						subnetRepository.update(subnet);
						// 保存子网路由关系
						RouterSubnet routerSubnet = new RouterSubnet(routerMap.get(srMap.get(subnet.getSubnetUuid())),
								subnet.getId(), vendorId);
						routerSubnetRepository.save(routerSubnet);
					}
				}
				// cmdb同步路由器
				for (Router router : routers) {
					List<CmdbRelation> relations = Lists.newArrayList();
					relations.add(
							new CmdbRelation(ModuleCode.OS_VENDOR.name(), 1L, ListUtils.getList(vendor.getGuid())));
					if (null != router.getNetworkId()) {
						Network network = networkRepository.query(router.getNetworkId());
						if (null != network) {
							relations.add(new CmdbRelation(ModuleCode.OS_VLAN.name(), 2L,
									ListUtils.getList(network.getGuid())));
						}
					}
					List<Subnet> nets = subnetRepository.listByRouterId(router.getId());
					for (Subnet net : nets) {
						relations.add(
								new CmdbRelation(ModuleCode.OS_SUBNET.name(), 2L, ListUtils.getList(net.getGuid())));
					}
					infos.add(CmdbInfoConvertor.getInfo(router, null, relations, CloudProvider.OPENSTACK));
				}
				// 同步防火墙策略
				logger.info("Starting sync firewall policy......");
				this.syncFirewallPolicy(model.getFirewallPolicyModels(), vendorId, 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(), vendorId, userId);
				logger.info("End sync firewall rule......");
				// 同步浮动IP
				logger.info("Starting sync floatingip......");
				this.syncFloatingIp(model.getfIpModels(), vendorId, userId, networkMap, portMap, routerMap);
				logger.info("End sync floatingip......");
				// 同步安全组
				logger.info("Starting sync security group......");
				this.syncSecurityGroup(model.getGroupModels(), vendorId, userId);
				logger.info("End sync security group......");
				// 同步虚拟机
				logger.info("Starting sync server......");
				Map<String, CloudServer> serverMap = new HashMap<>();
				this.syncServer(model.getServerModels(), vendorId, userId, hostMap, vendor.getType(), serverMap, infos,
						vendor.getGuid());
				// 同步虚拟 栈 从属关系
				this.syncServerStack(vendorId);
				logger.info("End sync server......");
				// 同步镜像
				Map<String, Image> imageMap = Maps.newHashMap();
				logger.info("Starting sync image......");
				this.syncImage(model.getImageModels(), vendorId, userId, vendor.getType(), imageMap);
				logger.info("End sync image......");
				// 同步云硬盘类型
				logger.info("Starting sync volume type......");
				this.syncVolumeType(model.getTypeModels(), vendorId);
				logger.info("End sync volume type......");
				// 同步块存储
				logger.info("Starting sync volume......");
				this.syncVolume(model.getVolumeModels(), vendorId, userId, serverMap, imageMap);
				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, volumeMap);
				logger.info("End sync snapshot......");
				// 同步规格
				logger.info("Starting sync flavor......");
				this.syncFlavor(model.getFlavorModels(), vendorId, userId);
				logger.info("End sync flavor......");
				// 同步负载均衡
				logger.info("Starting sync load balancer......");
				this.syncLoadBalancer(model.getLbModels(), vendorId, userId, subnetMap, portMap);
				logger.info("End sync load balancer......");
				// 同步密钥
				logger.info("Starting sync keypair......");
				this.syncKeypair(model.getKeypairModels(), vendorId, userId);
				logger.info("End sync keypair...");
				// 同步qos
				logger.info("Starting sync qos......");
				this.syncQoS(model.getGwQosModel(), vendorId, userId);
				logger.info("End sync qos...");
				// 同步VPN
				logger.info("Starting sync vpn service......");
				this.syncVpnService(model.getVpnModels(), vendorId, userId, routerMap, subnetMap);
				logger.info("End sync vpn service...");
				List<Vpn> vpns = vpnRepository.listByVendorId(vendorId);
				Map<String, Vpn> vpnsMap = Maps.newConcurrentMap();
				for (Vpn vpn : vpns) {
					vpnsMap.put(vpn.getVpnUuid(), vpn);
				}
				// 同步VPN POLICY
				logger.info("Starting sync vpn policy......");
				this.syncVpnPolicy(model.getVpnPolicyModels(), vendorId, userId);
				logger.info("End sync vpn policy...");
				List<VpnPolicy> vpnPolicys = vpnPolicyRepository.listByVendorId(vendorId);
				Map<String, VpnPolicy> vpnPolicysMap = Maps.newConcurrentMap();
				for (VpnPolicy vpnPolicy : vpnPolicys) {
					vpnPolicysMap.put(vpnPolicy.getPolicyUuid(), vpnPolicy);
				}
				// 同步VPN CONN
				logger.info("Starting sync vpn conn......");
				this.syncVpnConn(model.getVpnConnModes(), vendorId, userId, vpnsMap, vpnPolicysMap);
				logger.info("End sync vpn conn...");
			}
			// 删除IP表中不存在的脏数据
			ipService.processRubbishIp(vendor.getId());
			cmdbModel.setData(infos);
			messageDispatcher.cacheMessage(JSONObject.toJSONString(cmdbModel));
			return new BocloudResult(true, "云平台【 " + vendor.getName() + " 】数据同步成功");
		} catch (Exception e) {
			logger.error("Sync OpenStack error:{}", e);
			return new BocloudResult(false, "云平台【 " + vendor.getName() + " 】数据同步失败:" + e.getMessage());
		}
	}

	private void syncServerStack(Long vendorId) {
		try {
			// 栈ID 放到cloudserver env中
			Map<String, CloudStack> stackResources = stackResources(vendorId);
			if (null != stackResources && !stackResources.isEmpty()) {
				Set<Entry<String, CloudStack>> entrySet = stackResources.entrySet();
				for (Entry<String, CloudStack> entry : entrySet) {
					CloudStack cloudStack = entry.getValue();
					CloudServer cloudServer = cloudServerRepository.getByInstanceId(entry.getKey(), vendorId);
					if (null != cloudServer) {
						cloudServer.setEnv(cloudStack.getId());
						cloudServerRepository.update(cloudServer);
					}
				}
			}
		} catch (Exception e) {
			logger.error("同步虚拟栈关系异常：" + e.getMessage());
		}
	}

	private Map<String, CloudStack> stackResources(Long vendorId) {
		Map<String, CloudStack> cloudStackMap = Maps.newHashMap();
		try {
			List<CloudStack> cloudStacks = cloudStackRepository.listByVendorId(vendorId);
			for (CloudStack cloudStack : cloudStacks) {
				String resources = cloudStack.getResources();
				List<JSONObject> parseArray = JSON.parseArray(resources, JSONObject.class);
				if (null != parseArray && parseArray.size() > 0) {
					for (JSONObject jsonObject : parseArray) {
						String type = jsonObject.getString("type");
						if ("OS::Nova::Server".equalsIgnoreCase(type)) {
							String physicalResourceId = jsonObject.getString("physicalResourceId");
							cloudStackMap.put(physicalResourceId, cloudStack);
						}
					}
				}
			}
		} catch (Exception e) {
			logger.error("获取栈资源异常：" + e.getMessage());
		}
		return cloudStackMap;
	}

	private void syncVpnConn(List<VpnConnModel> vpnConnModes, Long vendorId, Long userId, Map<String, Vpn> vpnsMap,
			Map<String, VpnPolicy> vpnPolicysMap) throws Exception {
		if (ListTool.isEmpty(vpnConnModes)) {
			vpnConnRepository.removeByVid(vendorId, userId);
			return;
		}

		List<VpnConn> vpnConns = vpnConnRepository.listByVendorId(vendorId);
		Map<String, VpnConn> vpnConnsMap = Maps.newConcurrentMap();
		for (VpnConn vpnConn : vpnConns) {
			vpnConnsMap.put(vpnConn.getVpnConnUuid(), vpnConn);
		}
		for (VpnConnModel vpnConnModel : vpnConnModes) {
			VpnConn vpnConn = new VpnConn();
			if (vpnConnsMap.containsKey(vpnConnModel.getVpnConnUuid())) {
				vpnConn = vpnConnsMap.get(vpnConnModel.getVpnConnUuid());
				vpnConnModel.setRegion(vpnConn.getRegion());
				BeanUtils.copyProperties(vpnConnModel, vpnConn);
				vpnConn.setVendorId(vendorId);
				if (null != vpnsMap.get(vpnConnModel.getVpnUuid())) {
					vpnConn.setVpnId(vpnsMap.get(vpnConnModel.getVpnUuid()).getId());
				} else {
					vpnConn.setVpnId(0L);
				}
				if (null != vpnPolicysMap.get(vpnConnModel.getIkeUuid())) {
					vpnConn.setIkeId(vpnPolicysMap.get(vpnConnModel.getIkeUuid()).getId());
				} else {
					vpnConn.setIkeId(0L);
				}
				if (null != vpnPolicysMap.get(vpnConnModel.getIpsecUuid())) {
					vpnConn.setIpsecId(vpnPolicysMap.get(vpnConnModel.getIkeUuid()).getId());
				} else {
					vpnConn.setIpsecId(0L);
				}
				String peerCidrs = vpnConn.getPeerCidrs();
				String cidr = "";
				if (null != peerCidrs) {
					List<String> cidrs = JSONObject.parseArray(peerCidrs, String.class);
					for (String string : cidrs) {
						cidr += string + ",";
					}
				}
				if (cidr.length() > 0) {
					vpnConn.setPeerCidrs(cidr.substring(0, cidr.length() - 1));
				}
				vpnConn.setPeerId(vpnConn.getPeerAddress());
				vpnConnRepository.update(vpnConn);
				vpnConnsMap.remove(vpnConnModel.getVpnConnUuid());
				continue;
			}
			BeanUtils.copyProperties(vpnConnModel, vpnConn);
			vpnConn.setVpnId(null == vpnConnModel.getVpnId() ? 0L : vpnConnModel.getVpnId());
			vpnConn.setIkeId(null == vpnConnModel.getIkeId() ? 0L : vpnConnModel.getIkeId());
			vpnConn.setIpsecId(null == vpnConnModel.getIpsecId() ? 0L : vpnConnModel.getIpsecId());
			vpnConn.setVendorId(vendorId);
			vpnConn.setCreatorId(userId);
			vpnConn.setMenderId(userId);
			vpnConn.setTenantId(0L);
			String peerCidrs = vpnConn.getPeerCidrs();
			String cidr = "";
			if (null != peerCidrs) {
				List<String> cidrs = JSONObject.parseArray(peerCidrs, String.class);
				for (String string : cidrs) {
					cidr += string + ",";
				}
			}
			if (cidr.length() > 0) {
				vpnConn.setPeerCidrs(cidr.substring(0, cidr.length() - 1));
			}
			vpnConn.setPeerId(vpnConn.getPeerAddress());
			vpnConnRepository.save(vpnConn);
		}
		for (Entry<String, VpnConn> set : vpnConnsMap.entrySet()) {
			vpnConnRepository.remove(set.getValue().getId(), userId);
		}
	}

	private void syncVpnPolicy(List<VpnPolicyModel> vpnPolicyModels, Long vendorId, Long userId) throws Exception {
		if (ListTool.isEmpty(vpnPolicyModels)) {
			vpnPolicyRepository.removeByVid(vendorId, userId);
			return;
		}
		List<VpnPolicy> vpnPolicys = vpnPolicyRepository.listByVendorId(vendorId);
		Map<String, VpnPolicy> vpnPolicysMap = Maps.newConcurrentMap();
		for (VpnPolicy vpnPolicy : vpnPolicys) {
			vpnPolicysMap.put(vpnPolicy.getPolicyUuid(), vpnPolicy);
		}

		for (VpnPolicyModel vpnPolicyModel : vpnPolicyModels) {
			VpnPolicy vpnPolicy = new VpnPolicy();
			if (vpnPolicysMap.containsKey(vpnPolicyModel.getPolicyUuid())) {
				vpnPolicy = vpnPolicysMap.get(vpnPolicyModel.getPolicyUuid());
				vpnPolicyModel.setRegion(vpnPolicy.getRegion());
				BeanUtils.copyProperties(vpnPolicyModel, vpnPolicy);
				vpnPolicy.setVendorId(vendorId);
				vpnPolicyRepository.update(vpnPolicy);
				vpnPolicysMap.remove(vpnPolicyModel.getPolicyUuid());
				continue;
			}
			BeanUtils.copyProperties(vpnPolicyModel, vpnPolicy);
			vpnPolicy.setVendorId(vendorId);
			vpnPolicy.setCreatorId(userId);
			vpnPolicy.setMenderId(userId);
			vpnPolicy.setTenantId(0L);
			vpnPolicyRepository.save(vpnPolicy);
		}
		for (Entry<String, VpnPolicy> set : vpnPolicysMap.entrySet()) {
			vpnPolicyRepository.remove(set.getValue().getId(), userId);
		}
	}

	private void syncVpnService(List<VpnModel> vpnModels, Long vendorId, Long userId, Map<String, Long> routerMap,
			Map<String, Subnet> subnetMap) throws Exception {
		if (ListTool.isEmpty(vpnModels)) {
			vpnRepository.removeByVid(vendorId, userId);
			return;
		}
		List<Vpn> vpns = vpnRepository.listByVendorId(vendorId);
		Map<String, Vpn> vpnsMap = Maps.newConcurrentMap();
		for (Vpn vpn : vpns) {
			vpnsMap.put(vpn.getVpnUuid(), vpn);
		}
		for (VpnModel vpnModel : vpnModels) {
			Vpn vpn = new Vpn();
			if (vpnsMap.containsKey(vpnModel.getVpnUuid())) {
				vpn = vpnsMap.get(vpnModel.getVpnUuid());
				vpnModel.setRegion(vpn.getRegion());
				BeanUtils.copyProperties(vpnModel, vpn);
				vpn.setVendorId(vendorId);
				if (null != vpnModel.getRouterUuid()) {
					vpn.setRouterId(routerMap.get(vpnModel.getRouterUuid()));
				}
				if (null != vpnModel.getSubnetUuid()) {
					vpn.setSubnetId(null == subnetMap.get(vpnModel.getSubnetUuid()) ? 0L
							: subnetMap.get(vpnModel.getSubnetUuid()).getId());
				}
				vpnRepository.update(vpn);
				vpnsMap.remove(vpnModel.getVpnUuid());
				continue;
			}
			BeanUtils.copyProperties(vpnModel, vpn);
			vpn.setVendorId(vendorId);
			vpn.setCreatorId(userId);
			vpn.setMenderId(userId);
			vpn.setTenantId(0L);
			vpnRepository.save(vpn);
		}
		for (Entry<String, Vpn> set : vpnsMap.entrySet()) {
			vpnRepository.remove(set.getValue().getId(), userId);
		}
	}

	private void syncStackTemplateVersion(List<HeatStackModel> stackVersionModels, Long vendorId, Long userId)
			throws Exception {
		stackTemplateVersionRepository.removeByVid(vendorId, userId);
		if (null != stackVersionModels && stackVersionModels.size() > 0) {
			StackTemplateVersion stackTemplateVersion = null;
			for (HeatStackModel model : stackVersionModels) {
				stackTemplateVersion = new StackTemplateVersion();
				stackTemplateVersion.setVersion(model.getVersion());
				stackTemplateVersion.setFunctions(model.getFunctions());
				stackTemplateVersion.setAliases(model.getAliases());
				stackTemplateVersion.setType(model.getType());
				stackTemplateVersion.setVendorId(vendorId);
				stackTemplateVersion.setCreatorId(userId);
				stackTemplateVersion.setMenderId(userId);
				stackTemplateVersionRepository.save(stackTemplateVersion);
			}
		}
	}

	private void syncCloudStack(List<HeatStackModel> stackModels, Long vendorId, Long userId) throws Exception {
		// 清空数据库
		if (ListTool.isEmpty(stackModels)) {
			cloudStackRepository.removeByVid(vendorId, userId);
			return;
		}
		// 获取
		List<CloudStack> listByVendorId = cloudStackRepository.listByVendorId(vendorId);
		Map<String, CloudStack> clusterNodesMap = Maps.newHashMap();
		for (CloudStack stack : listByVendorId) {
			if (clusterNodesMap.containsKey(stack.getStackUuid())) {
				cloudStackRepository.remove(stack.getId(), userId);
			} else {
				clusterNodesMap.put(stack.getStackUuid(), stack);
			}
		}
		for (HeatStackModel model : stackModels) {
			CloudStack cloudStack = new CloudStack();
			if (clusterNodesMap.containsKey(model.getStackUuid())) {
				cloudStack = clusterNodesMap.get(model.getStackUuid());
				BeanUtils.copyProperties(model, cloudStack);
				cloudStack.setVendorId(vendorId);
				cloudStackRepository.update(cloudStack);
				cloudStackService.syncStackEvent(model, vendorId, cloudStack.getId());
				clusterNodesMap.remove(model.getStackUuid());
				continue;
			}
			BeanUtils.copyProperties(model, cloudStack);
			cloudStack.setVendorId(vendorId);
			cloudStack.setCreatorId(userId);
			cloudStack.setMenderId(userId);
			cloudStackRepository.save(cloudStack);
			cloudStackService.syncStackEvent(model, vendorId, cloudStack.getId());
			clusterNodesMap.remove(model.getStackUuid());
		}
		// 删除
		for (Entry<String, CloudStack> entry : clusterNodesMap.entrySet()) {
			cloudStackRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步OpenStack租户
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncOsTenant(List<OSTenantModel> models, Long vendorId, Long userId) throws Exception {
		if (ListTool.isEmpty(models)) {
			osTenantRepository.removeByVid(vendorId);
			return;
		}
		List<OSTenant> osTenants = osTenantRepository.listByVid(vendorId);
		Map<String, OSTenant> tenantMap = Maps.newHashMap();
		for (OSTenant oSTenant : osTenants) {
			if (tenantMap.containsKey(oSTenant.getTenantUuid())) {
				osTenantRepository.remove(oSTenant.getId());
			} else {
				tenantMap.put(oSTenant.getTenantUuid(), oSTenant);
			}
		}
		for (OSTenantModel model : models) {
			OSTenant osTenant = new OSTenant();
			if (tenantMap.containsKey(model.getTenantUuid())) {
				osTenant = tenantMap.get(model.getTenantUuid());
				BeanUtils.copyProperties(model, osTenant);
				osTenantRepository.update(osTenant);
				tenantMap.remove(model.getTenantUuid());
				continue;
			}
			BeanUtils.copyProperties(model, osTenant);
			osTenant.setCreatorId(userId);
			osTenant.setGmtCreate(new Date());
			osTenant.setVendorId(vendorId);
			osTenant.setTenantId(0L);
			osTenantRepository.save(osTenant);
			tenantMap.remove(model.getTenantUuid());
		}
		for (Entry<String, OSTenant> entry : tenantMap.entrySet()) {
			osTenantRepository.remove(entry.getValue().getId());
		}
	}

	private void syncHostResource(List<ClusterModel> hostResourcesModels, Long vendorId, Long userId) throws Exception {
		// 清空数据库
		if (ListTool.isEmpty(hostResourcesModels)) {
			clusterNodeRepository.removeByVendor(vendorId, userId);
			return;
		}
		// 获取
		List<ClusterNode> clusterNodes = clusterNodeRepository.listByVendor(vendorId);
		Map<String, ClusterNode> clusterNodesMap = Maps.newHashMap();
		for (ClusterNode clusterNode : clusterNodes) {
			if (clusterNodesMap.containsKey(clusterNode.getName() + "_" + clusterNode.getZone())) {
				clusterNodeRepository.remove(clusterNode.getId(), userId);
			} else {
				clusterNodesMap.put(clusterNode.getName() + "_" + clusterNode.getZone(), clusterNode);
			}
		}
		for (ClusterModel model : hostResourcesModels) {
			ClusterNode clusterNode = new ClusterNode();
			if (clusterNodesMap.containsKey(model.getName() + "_" + model.getZone())) {
				clusterNode = clusterNodesMap.get(model.getName() + "_" + model.getZone());
				clusterNode.setVendorId(vendorId);
				clusterNodeRepository.update(clusterNode);
				clusterNodesMap.remove(clusterNode.getName() + "_" + clusterNode.getZone());
				continue;
			}
			BeanUtils.copyProperties(model, clusterNode);
			clusterNode.setVendorId(vendorId);
			clusterNode.setCreatorId(userId);
			clusterNode.setMenderId(userId);
			clusterNodeRepository.save(clusterNode);
			clusterNodesMap.remove(clusterNode.getName() + "_" + clusterNode.getZone());
		}
		// 删除
		for (Entry<String, ClusterNode> entry : clusterNodesMap.entrySet()) {
			clusterNodeRepository.remove(entry.getValue().getId(), userId);
		}
	}

	private void syncQoS(List<GwQosModel> gwQosModel, Long vendorId, Long userId) throws Exception {
		// 清空数据库
		if (ListTool.isEmpty(gwQosModel)) {
			qosPolicyRepository.removeByVid(vendorId, userId);
			qosPolicyRulesRepository.removeByVid(vendorId, userId);
			return;
		}
		// 获取
		List<QosPolicy> policys = qosPolicyRepository.listByVendorId(vendorId);
		Map<String, QosPolicy> policysMap = Maps.newHashMap();
		for (QosPolicy policy : policys) {
			if (policysMap.containsKey(policy.getPolicyUuid())) {
				qosPolicyRepository.remove(policy.getId(), userId);
			} else {
				policysMap.put(policy.getPolicyUuid(), policy);
			}
		}
		for (GwQosModel model : gwQosModel) {
			QosPolicy policy = new QosPolicy();
			if (policysMap.containsKey(model.getPolicyUuid())) {
				policy = policysMap.get(model.getPolicyUuid());
				BeanUtils.copyProperties(model, policy);
				policy.setVendorId(vendorId);
				policy.setMenderId(userId);
				qosPolicyRepository.update(policy);
				qosPolicyRulesRepository.remove(model.getPolicyUuid(), vendorId, userId);
				if (null != model.getQosRules() && model.getQosRules().size() > 0) {
					List<GwQosModel> qosRules = model.getQosRules();
					for (GwQosModel ruleModel : qosRules) {
						QosPolicyRules rule = new QosPolicyRules();
						BeanUtils.copyProperties(ruleModel, rule);
						rule.setPolicyUuid(model.getPolicyUuid());
						rule.setVendorId(vendorId);
						rule.setCreatorId(userId);
						rule.setPolicyId(policy.getId());
						qosPolicyRulesRepository.save(rule);
					}
				}
				policysMap.remove(model.getPolicyUuid());
				continue;
			}
			BeanUtils.copyProperties(model, policy);
			policy.setVendorId(vendorId);
			policy.setCreatorId(userId);
			policy.setMenderId(userId);
			qosPolicyRepository.save(policy);
			qosPolicyRulesRepository.remove(model.getPolicyUuid(), vendorId, userId);
			if (null != model.getQosRules() && model.getQosRules().size() > 0) {
				List<GwQosModel> qosRules = model.getQosRules();
				for (GwQosModel ruleModel : qosRules) {
					QosPolicyRules rule = new QosPolicyRules();
					BeanUtils.copyProperties(ruleModel, rule);
					rule.setPolicyUuid(model.getPolicyUuid());
					rule.setVendorId(vendorId);
					rule.setCreatorId(userId);
					rule.setPolicyId(policy.getId());
					qosPolicyRulesRepository.save(rule);
				}
			}
			policysMap.remove(model.getPolicyUuid());
		}
		// 删除
		for (Entry<String, QosPolicy> entry : policysMap.entrySet()) {
			Long id = entry.getValue().getId();
			QosPolicy qosPolicy = qosPolicyRepository.query(id);
			qosPolicyRulesRepository.remove(qosPolicy.getPolicyUuid(), vendorId, userId);
			qosPolicyRepository.remove(id, userId);
		}

	}

	/**
	 * 同步负载均衡
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @param subnetMap
	 * @param portMap
	 * @throws Exception
	 */
	private void syncLoadBalancer(List<LbModel> models, Long vendorId, Long userId, Map<String, Subnet> subnetMap,
			Map<String, Long> portMap) throws Exception {
		// 当负载均衡为空时，清空数据库
		if (ListTool.isEmpty(models)) {
			lbMemberRepository.removeByVid(vendorId, userId);
			lbListenerRepository.removeByVid(vendorId, userId);
			loadBalancerRepository.removeByVid(vendorId, userId);
			lbPoolRepository.removeByVid(vendorId, userId);
			healthMonitorRepository.removeByVid(vendorId, userId);
			return;
		}
		// 获取负载均衡信息
		List<LoadBalancer> balancers = loadBalancerRepository.listByVid(vendorId);
		Map<String, LoadBalancer> balancerMap = Maps.newHashMap();
		for (LoadBalancer balancer : balancers) {
			if (balancerMap.containsKey(balancer.getLbUuid())) {
				loadBalancerRepository.remove(balancer.getId(), userId);
			} else {
				balancerMap.put(balancer.getLbUuid(), balancer);
			}
		}
		for (LbModel model : models) {
			boolean flag = true;
			Long lbId = null;
			if (balancerMap.containsKey(model.getLbUuid())) {
				flag = false;
				LoadBalancer balancer = balancerMap.get(model.getLbUuid());
				BeanUtils.copyProperties(model, balancer);
				balancer.setMenderId(userId);
				if (!StringUtils.isEmpty(balancer.getVipPortUuid())) {
					balancer.setPortId(portMap.get(balancer.getVipPortUuid()));
				} else {
					balancer.setPortId(null);
					balancer.setVipPortUuid(null);
				}
				loadBalancerRepository.update(balancer);
				balancerMap.remove(model.getLbUuid());
				lbId = balancer.getId();
			}
			if (flag) {
				LoadBalancer balancer = JSONObject.parseObject(JSONObject.toJSONString(model), LoadBalancer.class);
				Long subnetId = 0L;
				if (null != subnetMap.get(balancer.getSubnetUuid())) {
					subnetId = subnetMap.get(balancer.getSubnetUuid()).getId();
				}
				balancer.preSave(userId, userId, vendorId, subnetId, portMap.get(balancer.getVipPortUuid()), 0L, 0L);
				loadBalancerRepository.save(balancer);
				lbId = balancer.getId();
			}
			this.syncLbListener(model.getModels(), vendorId, userId, lbId, model.getLbUuid(), subnetMap);
		}
		// 删除不存在的负载均衡以及相关对象
		for (Entry<String, LoadBalancer> entry : balancerMap.entrySet()) {
			Long lbId = entry.getValue().getId();
			List<LbListener> lbListeners = lbListenerRepository.listByLbId(lbId);
			for (LbListener lbListener : lbListeners) {
				lbMemberRepository.removeByListenerId(lbListener.getId(), userId);
			}
			lbListenerRepository.removeByLbId(lbId, userId);
			loadBalancerRepository.remove(lbId, userId);
		}
	}

	/**
	 * 同步负载均衡监听器
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @param lbId
	 * @param lbUuid
	 * @param subnetMap
	 * @throws Exception
	 */
	private void syncLbListener(List<LbListenerModel> models, Long vendorId, Long userId, Long lbId, String lbUuid,
			Map<String, Subnet> subnetMap) throws Exception {
		// 当监听器为空时，清空数据库
		if (ListTool.isEmpty(models)) {
			List<LbListener> listeners = lbListenerRepository.listByLbId(lbId);
			for (LbListener listener : listeners) {
				healthMonitorRepository.removeByListenerId(listener.getId(), userId);
				lbPoolRepository.removeByListenerId(listener.getId(), userId);
				lbMemberRepository.removeByListenerId(listener.getId(), userId);
			}
			lbListenerRepository.removeByLbId(lbId, userId);
			return;
		}
		// 获取负载均衡监听器信息
		List<LbListener> listeners = lbListenerRepository.listByLbId(lbId);
		Map<String, LbListener> listenerMap = Maps.newHashMap();
		for (LbListener listener : listeners) {
			if (listenerMap.containsKey(listener.getListenerUuid())) {
				lbListenerRepository.remove(listener.getId(), userId);
			} else {
				listenerMap.put(listener.getListenerUuid(), listener);
			}
		}
		for (LbListenerModel model : models) {
			boolean flag = true;
			Long listenerId = null;
			Long poolId = null;
			if (listenerMap.containsKey(model.getListenerUuid())) {
				flag = false;
				LbListener listener = listenerMap.get(model.getListenerUuid());
				BeanUtils.copyProperties(model, listener);
				listener.setVendorId(vendorId);
				listener.setMenderId(userId);
				listener.setLbUuid(lbUuid);
				lbListenerRepository.update(listener);
				listenerId = listener.getId();
				LbPoolModel poolModel = model.getPoolModel();
				LbPool pool = lbPoolRepository.getByListenerId(listenerId);
				if (null != pool && null != poolModel) {// poolId存在，监听器pool池存在，更新数据库
					BeanUtils.copyProperties(poolModel, pool);
					pool.setMenderId(userId);
					lbPoolRepository.update(pool);
					poolId = pool.getId();
					HealthMonitor monitor = healthMonitorRepository.getByPoolId(poolId);
					if (null != monitor) {
						BeanUtils.copyProperties(poolModel.getModel(), monitor);
						monitor.setMenderId(userId);
						healthMonitorRepository.update(monitor);
					}
				} else if (null == pool && null != poolModel) {// poolId不存在，监听器pool池存在，添加数据库pool
					pool = JSONObject.parseObject(JSONObject.toJSONString(poolModel), LbPool.class);
					pool.setListenerUuid(listener.getListenerUuid());
					pool.preSave(userId, userId, vendorId, listenerId, 0L, 0L);
					lbPoolRepository.save(pool);
					poolId = pool.getId();
					if (null != poolModel.getModel()) {
						HealthMonitor monitor = JSONObject.parseObject(JSONObject.toJSONString(poolModel.getModel()),
								HealthMonitor.class);
						monitor.setPoolUuid(pool.getPoolUuid());
						monitor.preSave(userId, userId, vendorId, listenerId, poolId, 0L, 0L);
						healthMonitorRepository.save(monitor);
					}
				} else if (null != pool && null == poolModel) {// poolId存在，监听器pool池不存在，删除数据库pool
					healthMonitorRepository.removeByListenerId(listenerId, userId);
					lbPoolRepository.removeByListenerId(listenerId, userId);
					poolId = null;
				}
				listenerMap.remove(model.getListenerUuid());
			}
			if (flag) {
				LbPoolModel poolModel = model.getPoolModel();
				LbListener listener = JSONObject.parseObject(JSONObject.toJSONString(model), LbListener.class);
				listener.setLbUuid(lbUuid);
				listener.preSave(userId, userId, vendorId, lbId, 0L, 0L);
				lbListenerRepository.save(listener);
				listenerId = listener.getId();
				if (null != poolModel) {
					LbPool pool = JSONObject.parseObject(JSONObject.toJSONString(poolModel), LbPool.class);
					pool.setListenerUuid(listener.getListenerUuid());
					pool.preSave(userId, userId, vendorId, listenerId, 0L, 0L);
					lbPoolRepository.save(pool);
					poolId = pool.getId();
					if (null != poolModel.getModel()) {
						HealthMonitor monitor = JSONObject.parseObject(JSONObject.toJSONString(poolModel.getModel()),
								HealthMonitor.class);
						monitor.setPoolUuid(pool.getPoolUuid());
						monitor.preSave(userId, userId, vendorId, listenerId, poolId, 0L, 0L);
						healthMonitorRepository.save(monitor);
					}
				}
			}
			this.syncLbMember(model.getModels(), vendorId, userId, listenerId, poolId, subnetMap);
		}
		// 删除不存在的负载均衡监听器以及相关对象
		for (Entry<String, LbListener> entry : listenerMap.entrySet()) {
			lbMemberRepository.removeByListenerId(entry.getValue().getId(), userId);
			lbListenerRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步负责均衡成员
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @param listenerId
	 * @param poolId
	 * @param subnetMap
	 * @throws Exception
	 */
	private void syncLbMember(List<LbMemberModel> models, Long vendorId, Long userId, Long listenerId, Long poolId,
			Map<String, Subnet> subnetMap) throws Exception {
		// 当成员为空时，清空数据库
		if (ListTool.isEmpty(models)) {
			lbMemberRepository.removeByListenerId(listenerId, userId);
			return;
		}
		// 获取负载均衡监听器信息
		List<LbMember> members = lbMemberRepository.listByListenerId(listenerId);
		Map<String, LbMember> memberMap = Maps.newHashMap();
		for (LbMember member : members) {
			if (memberMap.containsKey(member.getMemberUuid())) {
				lbMemberRepository.remove(member.getId(), userId);
			} else {
				memberMap.put(member.getMemberUuid(), member);
			}
		}
		for (LbMemberModel model : models) {
			if (memberMap.containsKey(model.getMemberUuid())) {
				LbMember member = memberMap.get(model.getMemberUuid());
				BeanUtils.copyProperties(model, member);
				member.setMenderId(userId);
				lbMemberRepository.update(member);
				memberMap.remove(model.getMemberUuid());
				continue;
			}
			LbMember member = JSONObject.parseObject(JSONObject.toJSONString(model), LbMember.class);
			member.setName(model.getAddress());
			Long subnetId = 0L;
			if (null != subnetMap.get(model.getSubnetUuid())) {
				subnetId = subnetMap.get(model.getSubnetUuid()).getId();
			}
			member.preSave(userId, userId, vendorId, listenerId, poolId, subnetId, 0L, 0L);
			lbMemberRepository.save(member);
		}
		// 删除不存在的负载均衡监听器以及相关对象
		for (Entry<String, LbMember> entry : memberMap.entrySet()) {
			lbMemberRepository.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, Network> networkMap, Map<String, Long> portMap, Map<String, Long> routerMap) throws Exception {
		// 当浮动IP为空时，清空数据库
		if (ListTool.isEmpty(models)) {
			List<FloatingIp> floatingIps = floatingIpRepository.listByVid(vendorId);
			for (FloatingIp floatingIp : floatingIps) {
				objectRelationRepository.deleteByRid(floatingIp.getId(), ResourceCategory.FloatingIp.name());
			}
			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) {
			Network network = networkMap.get(model.getFloatingNetworkUuid());
			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()));
					fIp.setRouterId(routerMap.get(fIp.getRouterUuid()));
				}
				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()));
				fIp.setRouterId(routerMap.get(fIp.getRouterUuid()));
			}
			fIp.preSave(userId, userId, vendorId, null == network ? 0L : network.getId(), 0L, 0L);
			floatingIpRepository.save(fIp);
		}
		// 删除不存在的浮动IP
		for (Entry<String, FloatingIp> entry : fIpMap.entrySet()) {
			floatingIpRepository.remove(entry.getValue().getId(), userId);
			objectRelationRepository.deleteByRid(entry.getValue().getId(), ResourceCategory.FloatingIp.name());
		}
	}

	/**
	 * 同步安全组和规则
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	public 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());
				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 (Entry<String, SecurityGroup> entry : groupMap.entrySet()) {
			Long sgId = entry.getValue().getId();
			serverSgroupRepository.removeBySgid(sgId);
			securityGroupRuleRepository.removeBySgId(sgId, userId);
			securityGroupRepository.remove(sgId, userId);
		}

	}

	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 (Entry<String, SecurityGroupRule> entry : ruleMap.entrySet()) {
			securityGroupRuleRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步可用域 available zone
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncRegion(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) {
			mapRegion.put(region.getName(), region);
		}
		for (RegionModel model : models) {
			Region reg = new Region();
			if (mapRegion.containsKey(model.getName())) { // update
				reg = mapRegion.get(model.getName());
				reg.setVendorId(vendorId);
				BeanUtils.copyProperties(model, reg);
				reg.setRegionId(reg.getCode());
				regionRepository.update(reg);
				mapRegion.remove(model.getName());
			} else {
				BeanUtils.copyProperties(model, reg);
				reg.setVendorId(vendorId);
				reg.setRegionId(reg.getCode());
				regionRepository.save(reg);
				mapRegion.remove(model.getName());
			}
		}
		for (String keyset : mapRegion.keySet()) {
			regionRepository.delete(mapRegion.get(keyset).getId());
		}
	}

	/**
	 * 物理主机和该平台下的宿主机进行同步对比
	 *
	 * @param hostModels
	 * @param vendorId
	 * @param userId
	 * @param hostIdMap
	 * @param infos
	 * @throws Exception
	 */
	private void syncHost(List<HostModel> hostModels, Long vendorId, Long userId, Map<String, Server> hostIdMap,
			List<CmdbInfo> infos) throws Exception {
		if (ListTool.isEmpty(hostModels)) {
			List<Server> servers = serverRepository.listByVendor(vendorId);
			for (Server server : servers) {
				// cmdb删除宿主机
				infos.add(CmdbInfoConvertor.getInfo(server, null, "delete", null, CloudProvider.OPENSTACK));
				// 删除IP地址
				ipRepository.delete(server.getId(), "PM", vendorId);
			}
			serverRepository.removeByVendor(vendorId, userId);
			return;
		}
		List<Server> hosts = serverRepository.listByVendor(vendorId);
		Map<String, Server> hostMap = Maps.newHashMap();
		for (Server server : hosts) {
			hostMap.put(server.getUuid(), server);
		}
		for (HostModel hostModel : hostModels) {
			boolean flag = true;
			if (hostMap.containsKey(hostModel.getUuid())) {
				flag = false;
				Server host = hostMap.get(hostModel.getUuid());
				host.setMenderId(userId);
				hostModel.setId(host.getId());
				// TODO: 2020/1/16 add by 007 BeanUtils.copyProperties这里有坑。如果
				// HostModel里面增加了字段，且provider没有返回这个字段的值，那么host里面的该字段的值就会被清理掉。
				// TODO: 2020/1/16 add by 007
				// 我也不知道还有哪些坑，只增加了host.setOsCategory("OpenStack");
				BeanUtils.copyProperties(hostModel, host);
				if ("up".equalsIgnoreCase(hostModel.getPowerState())) {
					host.setPowerState(BocloudStatus.Server.RUNNING.name());
				} else if ("down".equalsIgnoreCase(hostModel.getPowerState())) {
					host.setPowerState(BocloudStatus.Server.STOPPED.name());
				}
				if ("enabled".equalsIgnoreCase(hostModel.getStatus())) {
					host.setStatus(BocloudStatus.Basic.ENABLED.name());
				} else if ("disabled".equalsIgnoreCase(hostModel.getStatus())) {
					host.setStatus(BocloudStatus.Basic.DISABLED.name());
				}
				host.setManageIp(hostModel.getHostIp());
				host.setHostname(hostModel.getHostName());
				host.setVendorId(vendorId);
				host.setOsCategory("OpenStack");
				serverRepository.update(host);
				// 处理IP地址
				if (!StringUtils.isEmpty(host.getManageIp())) {
					Ip ip = ipRepository.checkExist(host.getManageIp(), host.getId(), "PM", vendorId);
					if (null == ip) {
						ip = new Ip(host.getManageIp(), null, null, null, vendorId, IDFactory.instance().uuid(), null,
								IpStatus.used);
						ip.setCatalog("PM");
						ip.setTarget(host.getId());
						ipRepository.save(ip);
					}
				}
				// 更新资源
				Resource resource = resourceRepository.query(ResourceCategory.Computer.name(),
						ResourceCatalog.PHYSICAL.name(), host.getId());
				List<String> privateIps = Lists.newArrayList();
				privateIps.add(host.getManageIp());
				if (null == resource) {
					resource = new Resource(ResourceCategory.Computer.name(), ResourceCatalog.PHYSICAL.name(),
							host.getId(), JSONObject.toJSONString(privateIps), OSCategory.LINUX.name(), vendorId);
					resource.preSave(host.getName(), host.getPowerState(), userId, 0L);
					resource.setInventory(JSONObject.toJSONString(host));
					resourceRepository.save(resource);
				} else {
					resource.setName(host.getName());
					resource.setStatus(host.getPowerState());
					resource.setPrivateIps(JSONObject.toJSONString(privateIps));
					resource.setMenderId(userId);
					resourceRepository.update(resource);
				}
				// 更新主机配置信息
				ServerConfig config = serverConfigRepository.getBySid(host.getId());
				if (null != config) {
					config.setDiskCapacity(hostModel.getDiskTotal());
					config.setCpuHz(hostModel.getCpuTotal());
					config.setMemoryCapacity(hostModel.getMemTotal());
					config.setCpuAmount(hostModel.getCpuNum());
					config.setCpuMode(hostModel.getCpuModel());
					config.setCpuCore(hostModel.getCpuCore());
					config.setCpuUsed(hostModel.getCpuUsed());
					config.setMemUsed(hostModel.getMemUsed());
					config.setDiskUsed(hostModel.getDiskUsed());
					serverConfigRepository.update(config);
				} else {
					config = new ServerConfig();
					config.setDiskCapacity(hostModel.getDiskTotal());
					config.setCpuHz(hostModel.getCpuTotal());
					config.setMemoryCapacity(hostModel.getMemTotal());
					config.setCpuAmount(hostModel.getCpuNum());
					config.setCpuMode(hostModel.getCpuModel());
					config.setCpuCore(hostModel.getCpuCore());
					config.setCpuUsed(hostModel.getCpuUsed());
					config.setMemUsed(hostModel.getMemUsed());
					config.setDiskUsed(hostModel.getDiskUsed());
					config.setServerId(host.getId());
					config.setVendor(hostModel.getVendor());
					serverConfigRepository.save(config);
				}
				hostIdMap.put(host.getName(), host);
				hostMap.remove(hostModel.getUuid());
			}
			if (flag) {
				Server host = JSONObject.parseObject(JSONObject.toJSONString(hostModel), Server.class);
				host.setVendorId(vendorId);
				host.setCreatorId(userId);
				BeanUtils.copyProperties(hostModel, host);
				if ("up".equals(host.getPowerState())) {
					host.setPowerState(BocloudStatus.Server.RUNNING.name());
				} else if ("down".equals(host.getPowerState())) {
					host.setPowerState(BocloudStatus.Server.STOPPED.name());
				}
				if ("enabled".equalsIgnoreCase(hostModel.getStatus())) {
					host.setStatus(BocloudStatus.Basic.ENABLED.name());
				} else if ("disabled".equalsIgnoreCase(hostModel.getStatus())) {
					host.setStatus(BocloudStatus.Basic.DISABLED.name());
				}
				host.setResourceId(IDFactory.instance().uuid());
				host.setManageIp(hostModel.getHostIp());
				host.setOsCategory("OpenStack");
				host.setAssetCategory(ServerAssetCategory.HYPERVISOR.name());
				host.setHostname(hostModel.getHostName());
				host.setVendorId(vendorId);
				serverRepository.save(host);
				// 处理IP地址
				if (!StringUtils.isEmpty(host.getManageIp())) {
					Ip ip = new Ip(host.getManageIp(), null, null, null, vendorId, IDFactory.instance().uuid(), null,
							IpStatus.used);
					ip.setCatalog("PM");
					ip.setTarget(host.getId());
					ipRepository.save(ip);
				}
				// 保存主机配置信息
				ServerConfig config = new ServerConfig();
				config.setDiskCapacity(hostModel.getDiskTotal());
				config.setCpuHz(hostModel.getCpuTotal());
				config.setMemoryCapacity(hostModel.getMemTotal());
				config.setCpuAmount(hostModel.getCpuNum());
				config.setCpuMode(hostModel.getCpuModel());
				config.setCpuCore(hostModel.getCpuCore());
				config.setCpuUsed(hostModel.getCpuUsed());
				config.setMemUsed(hostModel.getMemUsed());
				config.setDiskUsed(hostModel.getDiskUsed());
				config.setServerId(host.getId());
				config.setVendor(hostModel.getVendor());
				serverConfigRepository.save(config);
				// 保存资源
				host.setConfig(config);
				List<String> privateIps = Lists.newArrayList();
				privateIps.add(host.getManageIp());
				Resource resource = new Resource(ResourceCategory.Computer.name(), ResourceCatalog.PHYSICAL.name(),
						host.getId(), JSONObject.toJSONString(privateIps), OSCategory.LINUX.name(), vendorId);
				resource.preSave(host.getName(), host.getPowerState(), userId, 0L);
				resource.setInventory(JSONObject.toJSONString(host));
				resourceRepository.save(resource);
				hostIdMap.put(host.getName(), host);
			}
		}
		for (Entry<String, Server> entry : hostMap.entrySet()) {
			Server server = entry.getValue();
			// cmdb删除宿主机
			infos.add(CmdbInfoConvertor.getInfo(server, null, "delete", null, CloudProvider.OPENSTACK));
			Long hostId = server.getId();
			serverAssetsRepository.removeBySid(hostId);
			serverConfigRepository.removeBySid(hostId);
			resourceRepository.remove(hostId, ResourceCategory.Computer.name(), ResourceCatalog.PHYSICAL.name(),
					userId);
			serverRepository.remove(hostId, userId);
			// 回收IP
			ipRepository.delete(hostId, "PM", vendorId);

		}
	}

	/**
	 * 虚拟机和该平台下的虚拟机进行同步对比
	 *
	 * @param serverModels
	 * @param vendorId
	 * @param userId
	 * @param hostMap
	 * @param type
	 * @param serverMap
	 * @param infos
	 * @param vendorGuid
	 * @throws Exception
	 */
	private void syncServer(List<ServerModel> serverModels, Long vendorId, Long userId, Map<String, Server> hostMap,
			String type, Map<String, CloudServer> serverMap, List<CmdbInfo> infos, String vendorGuid) throws Exception {
		if (ListTool.isEmpty(serverModels)) {
			List<CloudServer> servers = cloudServerRepository.listByVendorId(vendorId);
			for (CloudServer server : servers) {
				// cmdb删除虚拟机数据
				infos.add(CmdbInfoConvertor.getInfo(server, "delete", null, CloudProvider.OPENSTACK));
				serverSgroupRepository.removeBySid(server.getId());
				volumeRepository.detachVolumes(server.getId(), userId);
				objectRelationRepository.deleteByRid(server.getId(), ResourceCategory.Computer.name());
				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();
		// 不同OpenStack租户或项目下安全组名称可能重复，由于虚拟机底层数据只有安全组名称，因此这个地方key用名称加tenantUuid来确定唯一性
		for (SecurityGroup group : securityGroups) {
			groupMap.put(group.getName() + group.getTenantUuid(), group.getId());
		}
		for (ServerModel server : serverModels) {
			// 虚拟机与对象的关系
			List<CmdbRelation> relations = Lists.newArrayList();
			// relations.add(new CmdbRelation(ModuleCode.OS_VENDOR.name(), 1L,
			// ListUtils.getList(vendorGuid)));
			CloudServer vm = new CloudServer();
			boolean flag = true;
			// 设置内网IP
			List<NetworkBean> networkBeans = Lists.newArrayList();
			// key networkUuid
			Map<String, List<Port>> portMap = Maps.newHashMap();
			String privateIps = "";
			List<Port> ports = portRepository.listByDeviceId(server.getInstanceId(), vendorId);
			List<String> subnetGuids = Lists.newArrayList();
			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;
							}
							subnetGuids.add(subnet.getGuid());
							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);
				}
			}
			// cmdb:虚拟机与网络的关系
			relations.add(new CmdbRelation(ModuleCode.OS_SUBNET.name(), 2L, subnetGuids));
			// 更新已创建的虚拟机
			if (cloudSeverMap.containsKey(server.getInstanceId())) {
				flag = false;
				vm = cloudSeverMap.get(server.getInstanceId());
				vm.setRegion(server.getZone());
				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());
				}
				if (!StringUtils.isEmpty(vm.getHostName())) {
					vm.setHostId(hostMap.get(vm.getHostName()).getId());
				} else {
					vm.setHostId(0L);
				}
				vm.setPassword(server.getPassword());
				vm.setIsTemplate(false);
				vm.setGmtVmCreate(server.getGmtVmCreate());
				vm.setPrivateIps(privateIps);
				vm.setTenantUuid(server.getTenantUuid());
				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);
				if (StringUtils.isEmpty(vm.getHostName())) {
					vm.preSave(userId, userId, vendorId, 0L, null, null, 0L, 0L);
				} else {
					vm.preSave(userId, userId, vendorId, hostMap.get(vm.getHostName()).getId(), 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();
					}
				}
				vm.setTenantId(0L);
				vm.setProjectId(0L);
				vm.setMenderId(0L);
				vm.setOwnerId(0L);
				vm.setBusinessId(0L);
				server.setAccount(account);
				vm.setRegion(server.getZone());
				vm.setTenantUuid(server.getTenantUuid());
				cloudServerRepository.save(vm);
				// 更新资源表
				Resource resource = serverOperationHelper.syncOsVResource(vendorId, vm, userId);
				vm.setResource(resource);
			}
			if (!StringUtils.isEmpty(vm.getHostName())) {
				// cmdb:虚拟机与宿主机的关系
				relations.add(new CmdbRelation(ModuleCode.OS_PM.name(), 1L,
						ListUtils.getList(hostMap.get(vm.getHostName()).getGuid())));
				relations.add(new CmdbRelation(ModuleCode.OS_PM.name(), 2L,
						ListUtils.getList(hostMap.get(vm.getHostName()).getGuid())));
			}
			infos.add(CmdbInfoConvertor.getInfo(vm, null, relations, CloudProvider.OPENSTACK));
			serverMap.put(server.getInstanceId(), vm);
			// 同步存虚拟机和安全组关系，首先删除旧数据
			serverSgroupRepository.removeBySid(vm.getId());
			if (StringUtils.isEmpty(server.getGroups())) {
				continue;
			}
			// 虚拟机新安全组
			List<String> groups = JSONObject.parseArray(server.getGroups(), String.class);
			for (String group : groups) {
				Long groupId = groupMap.get(group + vm.getTenantUuid());
				if (null != groupId) {
					// 保存虚拟机和安全组关系
					serverSgroupRepository.save(new ServerSgroup(vm.getId(), groupId));
				}
			}
		}
		for (Entry<String, CloudServer> entry : cloudSeverMap.entrySet()) {
			CloudServer server = entry.getValue();
			objectRelationRepository.deleteByRid(server.getId(), ResourceCategory.Computer.name());
			// cmdb删除虚拟机数据
			infos.add(CmdbInfoConvertor.getInfo(server, "delete", null, CloudProvider.OPENSTACK));
			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
	 * @param infos
	 * @param vendorGuid
	 * @throws Exception
	 */
	private void syncNetwork(List<NetworkModel> models, Long vendorId, Long userId, List<CmdbInfo> infos,
			String vendorGuid) throws Exception {
		if (ListTool.isEmpty(models)) {
			List<Network> networks = networkRepository.listByVid(vendorId);
			for (Network network : networks) {
				// cmdb：删除网络
				infos.add(CmdbInfoConvertor.getInfo(network, "delete", null, CloudProvider.OPENSTACK));
				List<Subnet> subnets = subnetRepository.listByNetwork(network.getId());
				for (Subnet subnet : subnets) {
					// cmdb：删除网络
					infos.add(CmdbInfoConvertor.getInfo(subnet, "delete", null, CloudProvider.OPENSTACK));
					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());
				}
				vpcRepository.deleteByNetworkId(network.getId(), 1L);
			}
			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())) {
				vpcRepository.deleteByNetworkId(network.getId(), 1L);
				networkRepository.remove(network.getId(), userId);
			} else {
				netMap.put(network.getNetworkUuid(), network);
			}
		}
		for (NetworkModel model : models) {
			List<CmdbRelation> relations = Lists.newArrayList();
			relations.add(new CmdbRelation(ModuleCode.OS_VENDOR.name(), 2L, ListUtils.getList(vendorGuid)));
			Long networkId = null;
			String networkGuid = null;
			if (netMap.containsKey(model.getNetworkUuid())) {
				Network network = netMap.get(model.getNetworkUuid());
				model.setVendorId(network.getVendorId());
				BeanUtils.copyProperties(model, network);
				network.setMenderId(userId);
				networkRepository.update(network);
				netMap.remove(model.getNetworkUuid());
				networkId = network.getId();
				networkGuid = network.getGuid();
				List<Vpc> vpcs = vpcRepository.listByNetworkId(network.getId());
				for (Vpc vpc : vpcs) {
					vpc.setName(network.getName());
					vpcRepository.update(vpc);
				}
				// CMDB更新集群数据
				infos.add(CmdbInfoConvertor.getInfo(network, null, relations, CloudProvider.OPENSTACK));
			} else {
				Network network = JSONObject.parseObject(JSONObject.toJSONString(model), Network.class);
				if ("RUNNING".equalsIgnoreCase(network.getStatus())) {
					network.setStatus(BocloudStatus.Server.RUNNING.name());
				} else {
					network.setStatus(BocloudStatus.Server.EXCEPTION.name());
				}
				network.preSave(userId, userId, vendorId, null);
				networkRepository.save(network);
				networkId = network.getId();
				networkGuid = network.getGuid();
				// CMDB添加集群数据
				infos.add(CmdbInfoConvertor.getInfo(network, null, relations, CloudProvider.OPENSTACK));
			}
			this.syncSubnet(model.getSubnets(), vendorId, userId, networkId, infos, vendorGuid, networkGuid);
		}
		// 存在异常网络数据
		for (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();
			vpcRepository.deleteByNetworkId(network.getId(), 1L);
			// cmdb：删除网络
			infos.add(CmdbInfoConvertor.getInfo(network, "delete", null, CloudProvider.OPENSTACK));
			List<Subnet> subnets = subnetRepository.listByNetwork(network.getId());
			for (Subnet subnet : subnets) {
				// cmdb：删除网络
				infos.add(CmdbInfoConvertor.getInfo(subnet, "delete", null, CloudProvider.OPENSTACK));
				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, List<CmdbInfo> infos,
			String vendorGuid, String networkGuid) throws Exception {
		if (ListTool.isEmpty(models)) {
			List<Subnet> subnets = subnetRepository.listByNetwork(networkId);
			for (Subnet subnet : subnets) {
				// cmdb：删除网络
				infos.add(CmdbInfoConvertor.getInfo(subnet, "delete", null, CloudProvider.OPENSTACK));
				routerSubnetRepository.deleteBySubnet(subnet.getId());
				ipPoolRepository.removeBySubnetId(subnet.getId(), vendorId, userId);
				List<Port> ports = portRepository.listBySubnetUuid(subnet.getNetworkUuid());
				for (Port port : ports) {
					infos.add(CmdbInfoConvertor.getInfo(port, null, "delete", null, CloudProvider.OPENSTACK));
					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) {
			List<CmdbRelation> relations = Lists.newArrayList();
			relations.add(new CmdbRelation(ModuleCode.OS_VLAN.name(), 2L, ListUtils.getList(networkGuid)));
			if (subMap.containsKey(model.getSubnetUuid())) {
				Subnet subnet = subMap.get(model.getSubnetUuid());
				BeanUtils.copyProperties(model, subnet);
				subnet.setMenderId(userId);
				subnet.setNetworkId(networkId);
				List<Vpc> listByNetworkId = vpcRepository.listByNetworkId(networkId);
				if (!ListTool.isEmpty(listByNetworkId)) {
					subnet.setVpcId(listByNetworkId.get(0).getId());
				}
				subnetRepository.update(subnet);
//				syncIpPool(subnet, false, vendorId, userId, networkId);
				subMap.remove(model.getSubnetUuid());
				// CMDB更新子网数据
				infos.add(CmdbInfoConvertor.getInfo(subnet, null, relations, CloudProvider.OPENSTACK));
				continue;
			}
			Subnet subnet = new Subnet();
			BeanUtils.copyProperties(model, subnet);
			subnet.preSave(userId, userId, vendorId, networkId);
			List<Vpc> listByNetworkId = vpcRepository.listByNetworkId(networkId);
			if (!ListTool.isEmpty(listByNetworkId)) {
				subnet.setVpcId(listByNetworkId.get(0).getId());
			}
			subnetRepository.save(subnet);
//			syncIpPool(subnet, true, vendorId, userId, networkId);
			// CMDB添加集群数据
			infos.add(CmdbInfoConvertor.getInfo(subnet, null, relations, CloudProvider.OPENSTACK));
		}
		// 存在异常子网数据
		for (Entry<String, Subnet> entry : subMap.entrySet()) {
			Subnet subnet = entry.getValue();
			// cmdb：删除网络
			infos.add(CmdbInfoConvertor.getInfo(subnet, "delete", null, CloudProvider.OPENSTACK));
			ipRepository.deleteBySubnetId(subnet.getId(), vendorId);
			ipPoolRepository.removeBySubnetId(subnet.getId(), vendorId, userId);
			List<Port> ports = portRepository.listBySubnetUuid(subnet.getNetworkUuid());
			for (Port port : ports) {
				infos.add(CmdbInfoConvertor.getInfo(port, null, "delete", null, CloudProvider.OPENSTACK));
				portFixedIpRepository.deleteByPortId(port.getId());
			}
			portRepository.removeBySubnetId(subnet.getId(), userId);
			routerSubnetRepository.deleteBySubnet(subnet.getId());
			subnetRepository.remove(subnet.getId(), userId);
		}
	}

//	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.setName(subnet.getName());
//			pool.setMenderId(userId);
//			pool.setCreatorId(userId);
//			pool.setVersion(IPAddress.getVersion(subnet.getGateway()));
//			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.setName(subnet.getName());
//			pool.setMenderId(userId);
//			pool.setCreatorId(userId);
//			pool.setVersion(IPAddress.getVersion(subnet.getGateway()));
//			ipPoolRepository.save(pool);
//			return;
//		}
//		pool.setName(subnet.getName());
//		pool.setCidr(subnet.getCidr());
//		pool.setGateway(subnet.getGateway());
//		pool.setPools(subnet.getIpPools());
//		pool.setDnsNames(subnet.getDnsNames());
//		pool.setMenderId(userId);
//		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, Volume> volumeMap)
			throws Exception {
		if (ListTool.isEmpty(models)) {
			List<Snapshot> snapshots = snapshotRepository.listByVid(vendorId);
			for (Snapshot snapshot : snapshots) {
				objectRelationRepository.deleteByRid(snapshot.getId(), ResourceCategory.Snapshot.name());
			}
			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) {
			Volume volume = volumeMap.get(model.getVolumeUuid());
			if (snapshotMap.containsKey(model.getSnapshotUuid())) {
				Snapshot snapshot = snapshotMap.get(model.getSnapshotUuid());
				BeanUtils.copyProperties(model, snapshot);
				snapshot.setMenderId(userId);
				if (null != volume) {
					snapshot.setVolumeId(volume.getId());
					snapshot.setTenantUuid(volume.getTenantUuid());
				}
				snapshotRepository.update(snapshot);
				snapshotMap.remove(model.getSnapshotUuid());
			} else {
				Snapshot snapshot = JSONObject.parseObject(JSONObject.toJSONString(model), Snapshot.class);
				if (null != volume) {
					snapshot.setVolumeId(volume.getId());
					snapshot.setTenantUuid(volume.getTenantUuid());
				}
				snapshot.preSave(userId, userId, vendorId, null, 0L);
				snapshotRepository.save(snapshot);
			}
		}
		for (Entry<String, Snapshot> entry : snapshotMap.entrySet()) {
			snapshotRepository.remove(entry.getValue().getId(), userId);
			objectRelationRepository.deleteByRid(entry.getValue().getId(), ResourceCategory.Snapshot.name());
		}
	}

	/**
	 * 云硬盘同步
	 *
	 * @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) throws Exception {
		if (ListTool.isEmpty(volumeModels)) {
			List<Volume> volumes = volumeRepository.listByVendorId(vendorId);
			for (Volume volume : volumes) {
				objectRelationRepository.deleteByRid(volume.getId(), ResourceCategory.Storage.name());
			}
			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());
				BeanUtils.copyProperties(volumeModel, volume);
				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);
				}
				VolumeType type = volumeTypeRepository.getByName(volumeModel.getVolumeType(), vendorId);
				if (null == type) {
					type = volumeTypeRepository.getByUuid(volumeModel.getVolumeType(), vendorId);
				}
				if (null != type) {
					volume.setVolumeTypeId(type.getId());
				}
				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);
				// 同步块设备和虚拟机之间的挂载关系
				List<ServerVolumeModel> models = volumeModel.getModels();
				if (!ListTool.isEmpty(models)) {
					updateOsCategory(models, serverMap, imageMap, volume, userId);
				}
				VolumeType type = volumeTypeRepository.getByName(volumeModel.getVolumeType(), vendorId);
				if (null == type) {
					type = volumeTypeRepository.getByUuid(volumeModel.getVolumeType(), vendorId);
				}
				if (null != type) {
					volume.setVolumeTypeId(type.getId());
				}
				volume.setTenantId(0L);
				volume.setProjectId(0L);
				volume.setMenderId(0L);
				volume.setOwnerId(0L);
				volume.setBusinessId(0L);
				volumeRepository.save(volume);
			}
		}
		// 删除异常数据
		for (Entry<String, Volume> entry : volumeMap.entrySet()) {
			volumeRepository.remove(entry.getValue().getId(), userId);
			objectRelationRepository.deleteByRid(entry.getValue().getId(), ResourceCategory.Storage.name());
		}
	}

	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 != device && device.contains("/vda")) {// 挂载路径为/vda的是虚拟机的根磁盘
			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());
					server.setMenderId(userId);
					cloudServerRepository.update(server);
					resource.setOsCategory(osCategory);
					resourceRepository.update(resource);
				}
			}
		}
		if (null != server) {
			volume.setServerId(server.getId());
		}
		volume.setDevice(device);
	}

	/**
	 * 镜像同步
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @param type
	 * @param imageMap
	 * @throws Exception
	 */
	private void syncImage(List<ImageModel> models, Long vendorId, Long userId, String type,
			Map<String, Image> imageMap) throws Exception {
		if (ListTool.isEmpty(models)) {
			List<Image> images = imageRepository.listByVendorId(vendorId);
			for (Image image : images) {
				objectRelationRepository.deleteByRid(image.getId(), ResourceCategory.Image.name());
			}
			imageRepository.removeByVid(vendorId, userId);
			return;
		}
		List<Image> images = imageRepository.listByVendorId(vendorId);
		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);
				}
			}
		}
		List<Image> imageUpdate = new ArrayList<Image>();
		List<Image> imageInsert = 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());
					model.setRemark(image.getRemark());
					model.setOsCategory(image.getOsCategory());
					model.setOsName(image.getOsName());
					model.setOsVersion(image.getOsVersion());
					model.setDefaultUser(image.getDefaultUser());
					BeanUtils.copyProperties(model, image);
					image.setMenderId(userId);
					image.setVendorType(type);
					image.setDefaultUser(model.getDefaultUser());
					imageUpdate.add(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");
				imageInsert.add(image);
			} else {
				image = imagesMap.get(model.getImageUuid());
				if (null != image) {
					imageRepository.remove(image.getId(), userId);
					objectRelationRepository.deleteByRid(image.getId(), ResourceCategory.Image.name());
				}
			}
		}
		if (imageUpdate.size() > 0) {
			imageRepository.batchUpdate(imageUpdate, imageUpdate.size());
		}
		if (imageInsert.size() > 0) {
			imageRepository.batchSave(imageInsert, imageInsert.size());
		}
		for (Entry<String, Image> set : imagesMap.entrySet()) {
			imageRepository.remove(set.getValue().getId(), userId);
			objectRelationRepository.deleteByRid(set.getValue().getId(), ResourceCategory.Image.name());
		}
	}

	/**
	 * 规格同步
	 *
	 * @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 = new ArrayList<>();
		resultData.addAll(flavors);
		for (FlavorModel model : models) {
			boolean flag = true;
			for (Flavor flavor : flavors) {
				if (!StringUtils.isEmpty(flavor.getFlavorUuid())
						&& 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());
		}
	}

	private void syncPort(List<PortModel> portModels, Long vendorId, Long userId, Map<String, Network> networkMap,
			Map<String, Subnet> subnetMap, List<CmdbInfo> infos) 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);
				}
				infos.add(CmdbInfoConvertor.getInfo(port, null, "delete", null, CloudProvider.OPENSTACK));
				portFixedIpRepository.deleteByPortId(port.getId());
			}
			portRepository.removeByVid(vendorId, userId);
			return;
		}
		List<Port> ports = portRepository.listByVid(vendorId);
		savePort(portModels, vendorId, userId, networkMap, subnetMap, ports, infos);
	}

	private void savePort(List<PortModel> newPortModels, Long vendorId, Long userId, Map<String, Network> networkMap,
			Map<String, Subnet> subnetMap, List<Port> oldPorts, List<CmdbInfo> infos) throws Exception {
		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);
				}
				infos.add(CmdbInfoConvertor.getInfo(port, null, "delete", null, CloudProvider.OPENSTACK));
				portFixedIpRepository.deleteByPortId(port.getId());
				portRepository.remove(port.getId(), userId);
			} else {
				portsMap.put(port.getPortUuid(), port);
			}
		}
		for (PortModel portModel : newPortModels) {
			List<CmdbRelation> relations = Lists.newArrayList();
			List<PortFixedIpModel> fixedIpModels = portModel.getPortFixedIps();
			if (!ListTool.isEmpty(fixedIpModels)) {
				PortFixedIpModel model = fixedIpModels.get(0);
				Subnet subnet = subnetMap.get(model.getSubnetUuid());
				if (null != subnet) {
					relations.add(
							new CmdbRelation(ModuleCode.OS_SUBNET.name(), 2L, ListUtils.getList(subnet.getGuid())));
				}
			}
			Network network = networkMap.get(portModel.getNetworkUuid());
			Port port = new Port();
			boolean flag = true;
			if (portsMap.containsKey(portModel.getPortUuid())) {
				flag = false;
				port = portsMap.get(portModel.getPortUuid());
				BeanUtils.copyProperties(portModel, port);
				port.setVendorId(vendorId);
				port.setMenderId(userId);
				if (null != network) {
					port.setTenantUuid(network.getTenantUuid());
				}
				portRepository.update(port);
				batchSavePortFixedIp(portModel.getPortFixedIps(), port.getPortUuid(), port.getId(), vendorId);
				portsMap.remove(portModel.getPortUuid());
				if (!ListTool.isEmpty(relations)) {
					infos.add(CmdbInfoConvertor.getInfo(port, portModel.getPortFixedIps(), null, relations,
							CloudProvider.OPENSTACK));
				}
			}
			if (flag) {
				if (networkMap.containsKey(portModel.getNetworkUuid())) {
					BeanUtils.copyProperties(portModel, port);
					port.preSave(userId, userId, vendorId, null == network ? 0L : network.getId());
					portRepository.save(port);
					batchSavePortFixedIp(portModel.getPortFixedIps(), port.getPortUuid(), port.getId(), vendorId);
					if (!ListTool.isEmpty(relations)) {
						infos.add(CmdbInfoConvertor.getInfo(port, portModel.getPortFixedIps(), null, relations,
								CloudProvider.OPENSTACK));
					}
				}
			}

		}
		for (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);
			}
			infos.add(CmdbInfoConvertor.getInfo(port, null, "delete", null, CloudProvider.OPENSTACK));
			portFixedIpRepository.deleteByPortId(port.getId());
			portRepository.remove(port.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())) {
					// 没有修改 直接删掉就可以了
					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;
	}

	/**
	 * 指同步某网络下的端口
	 *
	 * @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 (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);
		}
	}

	private void syncRouter(List<RouterModel> models, Long vendorId, Long userId, Map<String, Network> networkMap,
			List<CmdbInfo> infos) throws Exception {
		if (ListTool.isEmpty(models)) {
			List<Router> routers = routerRepository.listByVid(vendorId);
			for (Router router : routers) {
				objectRelationRepository.deleteByRid(router.getId(), ResourceCategory.Router.name());
				// cmdb：删除路由
				infos.add(CmdbInfoConvertor.getInfo(router, "delete", null, CloudProvider.OPENSTACK));
				routerSubnetRepository.deleteByRouter(router.getId());
			}
			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);
			} else {
				routesMap.put(router.getRouterUuid(), router);
			}
		}
		for (RouterModel model : models) {
			Long networkId = null;
			if (!StringUtils.isEmpty(model.getNetworkUuid())) {
				Network network = networkMap.get(model.getNetworkUuid());
				if (null != network) {
					networkId = network.getId();
				}
			}
			Router router = new Router();
			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());
				continue;
			}
			BeanUtils.copyProperties(model, router);
			router.preSave(userId, userId, vendorId, networkId, 0L, 0L);
			routerRepository.save(router);
			routesMap.remove(model.getRouterUuid());
		}
		for (Entry<String, Router> entry : routesMap.entrySet()) {
			Router router = entry.getValue();
			routerRepository.remove(router.getId(), userId);
			routerSubnetRepository.deleteByRouter(router.getId());
			objectRelationRepository.deleteByRid(router.getId(), ResourceCategory.Router.name());
			// cmdb：删除路由
			infos.add(CmdbInfoConvertor.getInfo(router, "delete", null, CloudProvider.OPENSTACK));
		}
	}

	/**
	 * 同步防火墙
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncFirewall(List<FirewallModel> models, Long vendorId, Long userId, Map<String, Long> policyMap,
			Map<String, Long> 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) {
						// 更新防火墙与路由的绑定
						routerRepository.updateFirewallByRouterId(routerMap.get(routerUuid), 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) {
					// 更新防火墙与路由的绑定
					routerRepository.updateFirewallByRouterId(routerMap.get(routerUuid), firewall.getId(),
							firewall.getFirewallUuid());
				}
			}
		}
		for (Entry<String, Firewall> entry : firewallMap.entrySet()) {
			firewallRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步防火墙策略
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncFirewallPolicy(List<FirewallPolicyModel> models, Long vendorId, Long userId) throws Exception {
		if (ListTool.isEmpty(models)) {
			firewallPolicyRepository.removeByVid(vendorId, userId);
			return;
		}
		List<FirewallPolicy> policys = firewallPolicyRepository.listByVid(vendorId);
		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);
				firewallPolicyRepository.update(firewallPolicy);
				policyMap.remove(model.getPolicyUuid());
				continue;
			}
			BeanUtils.copyProperties(model, firewallPolicy);
			firewallPolicy.preSave(userId, userId, vendorId, 0L, 0L);
			firewallPolicyRepository.save(firewallPolicy);
			policyMap.remove(model.getPolicyUuid());
		}
		for (Entry<String, FirewallPolicy> entry : policyMap.entrySet()) {
			firewallPolicyRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 防火墙规则
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncFirewallRule(List<FirewallRuleModel> models, Long vendorId, Long userId) throws Exception {
		if (ListTool.isEmpty(models)) {
			firewallRuleRepository.removeByVid(vendorId, userId);
			return;
		}
		List<FirewallRule> rules = firewallRuleRepository.listByVid(vendorId);
		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(vendorId);
		for (FirewallRuleModel model : models) {
			FirewallRule rule = new FirewallRule();
			if (ruleMap.containsKey(model.getRuleUuid())) {
				rule = ruleMap.get(model.getRuleUuid());
				BeanUtils.copyProperties(model, rule);
				rule.setVendorId(vendorId);
				rule.setMenderId(userId);
				FirewallPolicy firewallPolicy = firewallPolicyRepository.queryByPolicyUuid(model.getPolicyUuid(),
						vendorId);
				if (null != firewallPolicy) {
					rule.setPolicyId(firewallPolicy.getId());
				} else {
					rule.setPolicyId(null);
					rule.setPolicyUuid(null);
				}
				firewallRuleRepository.update(rule);
				ruleMap.remove(model.getRuleUuid());
				continue;
			}
			BeanUtils.copyProperties(model, rule);
			rule.preSave(userId, userId, vendorId, 0L, 0L);
			FirewallPolicy firewallPolicy = firewallPolicyRepository.queryByPolicyUuid(model.getPolicyUuid(), vendorId);
			if (null != firewallPolicy) {
				rule.setPolicyId(firewallPolicy.getId());
			}
			firewallRuleRepository.save(rule);
			ruleMap.remove(model.getRuleUuid());
		}
		for (Entry<String, FirewallRule> entry : ruleMap.entrySet()) {
			firewallRuleRepository.remove(entry.getValue().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 (Entry<String, Keypair> entry : keypairMap.entrySet()) {
			keypairRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步云硬盘类型
	 *
	 * @param models
	 * @param vendorId
	 * @throws Exception
	 */
	private void syncVolumeType(List<VolumeTypeModel> models, Long vendorId) throws Exception {
		if (ListTool.isEmpty(models)) {
			volumeTypeRepository.deleteByVendorId(vendorId);
			return;
		}
		List<VolumeType> types = volumeTypeRepository.listByVendorId(vendorId);
		Map<String, VolumeType> typeMap = Maps.newHashMap();
		for (VolumeType type : types) {
			if (typeMap.containsKey(type.getVolumeTypeUuid())) {
				volumeTypeRepository.remove(type.getId());
			} else {
				typeMap.put(type.getVolumeTypeUuid(), type);
			}
		}
		for (VolumeTypeModel model : models) {
			VolumeType type = new VolumeType();
			if (typeMap.containsKey(type.getVolumeTypeUuid())) {
				type = typeMap.get(type.getVolumeTypeUuid());
				BeanUtils.copyProperties(model, type);
				volumeTypeRepository.update(type);
				typeMap.remove(model.getName());
				continue;
			}
			BeanUtils.copyProperties(model, type);
			type.setVendorId(vendorId);
			volumeTypeRepository.save(type);
			typeMap.remove(model.getName());
		}
		for (Entry<String, VolumeType> entry : typeMap.entrySet()) {
			volumeTypeRepository.remove(entry.getValue().getId());
		}
	}

	/**
	 * 同步主机组
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @param infos
	 * @param vendorGuid
	 * @param newClusterMap
	 * @throws Exception
	 */
	private void syncHostAggregate(List<ClusterModel> models, Long vendorId, Long userId, List<CmdbInfo> infos,
			String vendorGuid, Map<Long, Cluster> newClusterMap) throws Exception {
		if (ListTool.isEmpty(models)) {
			List<Cluster> clusters = clusterRepository.listByVendor(vendorId);
			for (Cluster cluster : clusters) {
				// cmdb：删除集群
				infos.add(CmdbInfoConvertor.getInfo(cluster, "delete", null, CloudProvider.OPENSTACK));
			}
			clusterRepository.removeByVendor(vendorId, userId);
			return;
		}
		List<Cluster> clusters = clusterRepository.listByVendor(vendorId);
		Map<String, Cluster> clusterMap = Maps.newHashMap();
		for (Cluster cluster : clusters) {
			if (clusterMap.containsKey(cluster.getName())) {
				// cmdb：删除集群
				infos.add(CmdbInfoConvertor.getInfo(cluster, "delete", null, CloudProvider.OPENSTACK));
				clusterRepository.remove(cluster.getId(), userId);
			} else {
				clusterMap.put(cluster.getName(), cluster);
			}
		}
		// 重置主机与主机组关系
		List<Server> servers = serverRepository.listByVendor(vendorId);
		for (Server server : servers) {
			server.setClusterId(null);
			server.setGmtModify(new Date());
			server.setMenderId(userId);
			serverRepository.update(server);
		}
		List<ClusterNode> clusterNodes = clusterNodeRepository.listByVendor(vendorId);
		for (ClusterNode clusterNode : clusterNodes) {
			clusterNode.setClusterId(null);
			clusterNode.setGmtModify(new Date());
			clusterNode.setMenderId(userId);
			clusterNodeRepository.update(clusterNode);
		}
		for (ClusterModel model : models) {
			Cluster cluster = new Cluster();
			Long clusterId = null;
			List<CmdbRelation> relations = Lists.newArrayList();
			relations.add(new CmdbRelation(ModuleCode.OS_VENDOR.name(), 1L, ListUtils.getList(vendorGuid)));
			if (clusterMap.containsKey(model.getName())) {
				cluster = clusterMap.get(model.getName());
				BeanUtils.copyProperties(model, cluster);
				Region region = regionRepository.getByName(model.getRegion(), vendorId);
				if (null != region) {
					cluster.setRegionId(region.getId());
				}
				cluster.setMenderId(userId);
				cluster.setGmtModify(new Date());
				cluster.setType(CloudProvider.OPENSTACK.name());
				clusterRepository.update(cluster);
				clusterId = cluster.getId();
				clusterMap.remove(model.getName());
				List<String> hostIds = model.getHostNames();
				if (!ListTool.isEmpty(hostIds)) {
					for (String hostId : hostIds) {
						ClusterNode clusterNode = clusterNodeRepository.getByName(hostId, vendorId);
						if (null != clusterNode) {
							clusterNode.setClusterId(clusterId);
							clusterNode.setGmtModify(new Date());
							clusterNode.setMenderId(userId);
							clusterNodeRepository.update(clusterNode);
						}
						Server byHostName = serverRepository.getByHostName(hostId, vendorId);
						if (null != byHostName) {
							byHostName.setClusterId(clusterId);
							byHostName.setGmtModify(new Date());
							byHostName.setMenderId(userId);
							serverRepository.update(byHostName);
						}
					}
				}
				infos.add(CmdbInfoConvertor.getInfo(cluster, null, relations, CloudProvider.OPENSTACK));
				newClusterMap.put(clusterId, cluster);
				continue;
			}
			BeanUtils.copyProperties(model, cluster);
			cluster.setCreatorId(userId);
			cluster.setGmtCreate(new Date());
			cluster.setVendorId(vendorId);
			cluster.setType(CloudProvider.OPENSTACK.name());
			Region region = regionRepository.getByName(model.getRegion(), vendorId);
			if (null != region) {
				cluster.setRegionId(region.getId());
			}
			clusterRepository.save(cluster);
			clusterId = cluster.getId();
			clusterMap.remove(model.getName());
			List<String> hostIds = model.getHostNames();
			if (!ListTool.isEmpty(hostIds)) {
				for (String hostId : hostIds) {
					ClusterNode clusterNode = clusterNodeRepository.getByName(hostId, vendorId);
					if (null != clusterNode) {
						clusterNode.setClusterId(clusterId);
						clusterNode.setGmtModify(new Date());
						clusterNode.setMenderId(userId);
						clusterNodeRepository.update(clusterNode);
					}
					Server byHostName = serverRepository.getByHostName(hostId, vendorId);
					if (null != byHostName) {
						byHostName.setClusterId(clusterId);
						byHostName.setGmtModify(new Date());
						byHostName.setMenderId(userId);
						serverRepository.update(byHostName);
					}
				}
			}
			newClusterMap.put(clusterId, cluster);
			infos.add(CmdbInfoConvertor.getInfo(cluster, null, relations, CloudProvider.OPENSTACK));
		}
		for (Entry<String, Cluster> entry : clusterMap.entrySet()) {
			infos.add(CmdbInfoConvertor.getInfo(entry.getValue(), "delete", null, CloudProvider.OPENSTACK));
			clusterRepository.remove(entry.getValue().getId(), userId);
		}
	}

	public OpenstackTransportor(NetworkRepository networkRepository, SubnetRepository subnetRepository,
			PortRepository portRepository, IpRepository ipRepository, LoadBalancerRepository loadBalancerRepository,
			LbListenerRepository lbListenerRepository, LbMemberRepository lbMemberRepository,
			LbPoolRepository lbPoolRepository, HealthMonitorRepository healthMonitorRepository,
			PortFixedIpRepository portFixedIpRepository, IpPoolRepository ipPoolRepository, IpService ipService) {
		super();
		this.networkRepository = networkRepository;
		this.subnetRepository = subnetRepository;
		this.portRepository = portRepository;
		this.ipRepository = ipRepository;
		this.loadBalancerRepository = loadBalancerRepository;
		this.lbListenerRepository = lbListenerRepository;
		this.lbMemberRepository = lbMemberRepository;
		this.lbPoolRepository = lbPoolRepository;
		this.healthMonitorRepository = healthMonitorRepository;
		this.portFixedIpRepository = portFixedIpRepository;
		this.ipPoolRepository = ipPoolRepository;
		this.ipService = ipService;
	}

	public BocloudResult syncStack(CloudVendor vendor, Object data, Long userId) {
		try {
			if (null != data) {
				Long vendorId = vendor.getId();
				String content = JSONObject.toJSONString(data);
				OSSyncModel model = JSONObject.parseObject(content, OSSyncModel.class);
				// 获取平台网络信息
				Map<String, Network> networkMap = Maps.newHashMap();
				List<Network> networks = networkRepository.listByVid(vendorId);
				for (Network network : networks) {
					networkMap.put(network.getNetworkUuid(), network);
				}
				// 获取平台网络子网信息
				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.syncStackPort(model.getPortModels(), vendorId, userId, networkMap, subnetMap);
				logger.info("End sync port......");
				// 同步负载均衡
				logger.info("Starting sync load balancer......");
				this.syncStackLoadBalancer(model.getLbModels(), vendorId, userId);
				logger.info("End sync load balancer......");
			}
			return new BocloudResult(true, "云平台【 " + vendor.getName() + " 】数据同步成功");
		} catch (Exception e) {
			logger.error("Sync OpenStack error:{}", e);
			return new BocloudResult(false, "云平台【 " + vendor.getName() + " 】数据同步失败");
		}
	}

	public void syncStackPort(List<PortModel> portModels, Long vendorId, Long userId, Map<String, Network> networkMap,
			Map<String, Long> subnetMap) throws Exception {
		if (ListTool.isEmpty(portModels)) {
			return;
		}
		for (PortModel portModel : portModels) {
			Port dbPort = portRepository.getByPortUuid(portModel.getPortUuid(), vendorId);
			if (null == dbPort) {
				Network network = networkMap.get(portModel.getNetworkUuid());
				Port port = new Port();
				if (networkMap.containsKey(portModel.getNetworkUuid())) {
					BeanUtils.copyProperties(portModel, port);
					port.preSave(userId, userId, vendorId, null == network ? 0L : network.getId());
					portRepository.save(port);
					batchSavePortFixedIp(portModel.getPortFixedIps(), port.getPortUuid(), port.getId(), vendorId);
				}
			}
		}
	}

	private void syncStackLoadBalancer(List<LbModel> models, Long vendorId, Long userId) throws Exception {
		if (ListTool.isEmpty(models)) {
			return;
		}
		LbModel lbModel = models.get(0);
		LoadBalancer balancer = loadBalancerRepository.queryByUuid(lbModel.getLbUuid(), vendorId);
		Long lbId = null;
		if (null == balancer) {
			balancer = JSONObject.parseObject(JSONObject.toJSONString(lbModel), LoadBalancer.class);
			balancer.preSave(userId, userId, vendorId, null, null, 0L, 0L);
			Port byPortUuid = portRepository.getByPortUuid(balancer.getVipPortUuid(), vendorId);
			if (null != byPortUuid) {
				balancer.setPortId(byPortUuid.getId());
			}
			Subnet subnet = subnetRepository.getBySubId(balancer.getSubnetUuid());
			if (null != subnet) {
				balancer.setSubnetId(subnet.getId());
			}
			loadBalancerRepository.save(balancer);
			lbId = balancer.getId();
		} else {
			lbId = balancer.getId();
		}
		this.syncStackLbListener(lbModel.getModels(), vendorId, userId, lbId, lbModel.getLbUuid());
	}

	private void syncStackLbListener(List<LbListenerModel> models, Long vendorId, Long userId, Long lbId, String lbUuid)
			throws Exception {
		if (ListTool.isEmpty(models)) {
			return;
		}
		LbListenerModel model = models.get(0);
		LbListener listener = lbListenerRepository.queryByUuid(model.getListenerUuid(), vendorId);
		Long listenerId = null;
		Long poolId = null;
		if (null == listener) {
			LbPoolModel poolModel = model.getPoolModel();
			listener = JSONObject.parseObject(JSONObject.toJSONString(model), LbListener.class);
			listener.setLbUuid(lbUuid);
			listener.preSave(userId, userId, vendorId, lbId, 0L, 0L);
			lbListenerRepository.save(listener);
			listenerId = listener.getId();
			if (null != poolModel) {
				LbPool pool = JSONObject.parseObject(JSONObject.toJSONString(poolModel), LbPool.class);
				pool.setListenerUuid(listener.getListenerUuid());
				pool.preSave(userId, userId, vendorId, listenerId, 0L, 0L);
				lbPoolRepository.save(pool);
				poolId = pool.getId();
				if (null != poolModel.getModel()) {
					HealthMonitor monitor = JSONObject.parseObject(JSONObject.toJSONString(poolModel.getModel()),
							HealthMonitor.class);
					monitor.setPoolUuid(pool.getPoolUuid());
					monitor.preSave(userId, userId, vendorId, listenerId, poolId, 0L, 0L);
					healthMonitorRepository.save(monitor);
				}
			}
		} else {
			listenerId = listener.getId();
			LbPool lbPool = lbPoolRepository.getByListenerId(listenerId);
			if (null != lbPool) {
				poolId = lbPool.getId();
			}
		}
		if (null != listenerId && null != poolId) {
			this.syncStackLbMember(model.getModels(), vendorId, userId, listenerId, poolId);
		}
	}

	public void syncStackLbMember(List<LbMemberModel> models, Long vendorId, Long userId, Long listenerId, Long poolId)
			throws Exception {
		if (ListTool.isEmpty(models)) {
			return;
		}
		lbMemberRepository.removeByListenerId(listenerId, userId);
		List<LbMember> members = new ArrayList<LbMember>();
		for (LbMemberModel model : models) {
			LbMember member = JSONObject.parseObject(JSONObject.toJSONString(model), LbMember.class);
			member.setName(model.getAddress());
			member.preSave(userId, userId, vendorId, listenerId, poolId, null, 0L, 0L);
			Subnet subnet = subnetRepository.getBySubId(model.getSubnetUuid());
			if (null != subnet) {
				member.setSubnetId(subnet.getId());
			}
			members.add(member);
		}
		if (!members.isEmpty()) {
			lbMemberRepository.batchSave(members, members.size());
		}
	}

	public OpenstackTransportor(SecurityGroupRepository securityGroupRepository,
			SecurityGroupRuleRepository securityGroupRuleRepository, ServerSgroupRepository serverSgroupRepository) {
		super();
		this.securityGroupRepository = securityGroupRepository;
		this.securityGroupRuleRepository = securityGroupRuleRepository;
		this.serverSgroupRepository = serverSgroupRepository;
	}
}