package com.bocloud.ims.service.resource;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.bocloud.cmp.model.common.OrderItem;
import com.bocloud.cmp.model.common.OrderMessage;
import com.bocloud.cmp.model.common.ServiceOrder;
import com.bocloud.cmp.model.common.OrderMessage.Operation;
import com.bocloud.cmp.vm.model.ResourceAssignParam;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.common.enums.ResourceCatalog;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.model.RequestContext.Catalog;
import com.bocloud.common.utils.DateTools;
import com.bocloud.common.utils.ListTool;
import com.bocloud.ims.entity.common.Project;
import com.bocloud.ims.entity.resource.CloudServer;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.ElasticIp;
import com.bocloud.ims.entity.resource.FloatingIp;
import com.bocloud.ims.entity.resource.Image;
import com.bocloud.ims.entity.resource.LoadBalancer;
import com.bocloud.ims.entity.resource.Network;
import com.bocloud.ims.entity.resource.NetworkInterface;
import com.bocloud.ims.entity.resource.OSTenant;
import com.bocloud.ims.entity.resource.ObjectRelation;
import com.bocloud.ims.entity.resource.PoolGroup;
import com.bocloud.ims.entity.resource.Resource;
import com.bocloud.ims.entity.resource.ResourceQuota;
import com.bocloud.ims.entity.resource.ResourceQuota.Action;
import com.bocloud.ims.entity.resource.SecurityGroup;
import com.bocloud.ims.entity.resource.Snapshot;
import com.bocloud.ims.entity.resource.TenantNetwork;
import com.bocloud.ims.entity.resource.TenantProvider;
import com.bocloud.ims.entity.resource.Volume;
import com.bocloud.ims.entity.resource.Vpc;
import com.bocloud.ims.interfaces.resource.ResourceAllocateService;
import com.bocloud.ims.interfaces.resource.ResourcePoolService;
import com.bocloud.ims.repository.resource.CloudServerRepository;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.ElasticIpRepository;
import com.bocloud.ims.repository.resource.FloatingIpRepository;
import com.bocloud.ims.repository.resource.ImageRepository;
import com.bocloud.ims.repository.resource.LoadBalancerRepository;
import com.bocloud.ims.repository.resource.NetworkInterfaceRepository;
import com.bocloud.ims.repository.resource.NetworkRepository;
import com.bocloud.ims.repository.resource.OSTenantRepository;
import com.bocloud.ims.repository.resource.ObjectRelationRepository;
import com.bocloud.ims.repository.resource.ResourceRepository;
import com.bocloud.ims.repository.resource.SecurityGroupRepository;
import com.bocloud.ims.repository.resource.SnapshotRepository;
import com.bocloud.ims.repository.resource.TenantNetworkRepository;
import com.bocloud.ims.repository.resource.TenantProviderRepository;
import com.bocloud.ims.repository.resource.VolumeRepository;
import com.bocloud.ims.repository.resource.VpcRepository;
import com.bocloud.ims.service.internal.CosInternalService;
import com.bocloud.ims.service.internal.ResourceOrderService;
import com.bocloud.ims.service.internal.SmsProjectService;
import com.bocloud.ims.service.internal.SmsUserService;
import com.bocloud.nms.enums.ChargeCommon;
import com.bocloud.nms.enums.OrderItemStatus;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Lists;

/**
 * 资源分配给项目service接口实现
 *
 * @author wangyu
 * @version 4.1.0-SNAPSHOT
 * @since 2019/2/28
 */
@Service("resourceAllocateService")
public class ResourceAllocateServiceImpl implements ResourceAllocateService {

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

	@Autowired
	private CloudServerRepository cloudServerRepository;
	@Autowired
	private VolumeRepository volumeRepository;
	@Autowired
	private SnapshotRepository snapshotRepository;
	@Autowired
	private ImageRepository imageRepository;
	@Autowired
	private CloudVendorRepository cloudVendorRepository;
	@Autowired
	private ObjectRelationRepository objectRelationRepository;
	@Autowired
	private ResourceRepository resourceRepository;
	@Autowired
	private FloatingIpRepository floatingIpRepository;
	@Autowired
	private SmsUserService smsUserService;
	@Autowired
	private SmsProjectService smsProjectService;
	@Autowired
	private LockFactory lockFactory;
	@Autowired
	private CosInternalService cosInternalService;
	@Autowired
	private ResourceOrderService resourceOrderService;
	@Autowired
	private NetworkInterfaceRepository networkInterfaceRepository;
	@Autowired
	private VpcRepository vpcRepository;
	@Autowired
	private ElasticIpRepository elasticIpRepository;
	@Autowired
	private NetworkRepository networkRepository;
	@Autowired
	private AmqpTemplate amqpTemplate;
	@Autowired
	private LoadBalancerRepository loadBalancerRepository;
	@Autowired
	private SecurityGroupRepository securityGroupRepository;
	@Autowired
	private TenantProviderRepository tenantProviderRepository;
	@Autowired
	private ResourcePoolService resourcePoolService;
	@Autowired
	private OSTenantRepository osTenantRepository;
	@Autowired
	private TenantNetworkRepository tenantNetworkRepository;

	@Override
	public BocloudResult assign(JSONObject object, ResourceCategory category, RequestContext context) {
		// 资源ID
		List<Long> serverIds = JSON.parseArray(object.getString("ids"), Long.class);
		if (ListTool.isEmpty(serverIds)) {
			return new BocloudResult<>(false, "无资源分配");
		}
		// 租户用户ID
		Long userId = object.getLong("userId");
		// 租户用户所在项目
		Long projectId = object.getLong("projectId") == null ? 0L : object.getLong("projectId");
		// 租户ID
		Long tenantId = object.getLong("tenantId") == null ? 0L : object.getLong("tenantId");
		if(projectId == 0 && tenantId == 0) {
			return new BocloudResult<>(false, "参数格式错误");
		}
		if(tenantId == 0 && projectId != 0) {
			BocloudResult<Project> bocloudResult = smsProjectService.detail(projectId);
			if(bocloudResult.isFailed()) {
				return bocloudResult;
			}
			Project project = bocloudResult.getData();
			tenantId = project.getTenantId();
		}
		String path = null;
		CloudVendor vendor = null;
		BocloudResult result = null;
		if (null == category) {
			category = ResourceCategory.Computer;
		}
		try {
			for (Long id : serverIds) {
				List<ResourceQuota> quotas = new ArrayList<>();
				// 生成的订单
				List<ServiceOrder> orders = new ArrayList<>();
				// 生成的订单明细
				List<OrderItem> items = new ArrayList<>();
				switch (category) {
				case Computer:
					path = CloudServer.class.getSimpleName() + "_" + id;
					try (BocloudACLock lock = lockFactory.getACLock(path)) {
						Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
						CloudServer server = cloudServerRepository.query(id);
						Assert.notNull(server, "虚拟机不存在");
						Long serverTenantId = server.getTenantId();
						if (null != serverTenantId && serverTenantId != 0) {
							return new BocloudResult(false, "虚拟机【" + server.getName() + "】分配失败，当前虚机已属于租户");
						}
						vendor = cloudVendorRepository.query(server.getVendorId());
						Assert.notNull(vendor, "云平台不存在");
						Integer cpu = server.getCpu();
						BigDecimal memory = server.getMemory();
						Integer disk = 0;
						Integer eip = 0;
						FloatingIp floatingIp = null;
						ElasticIp elasticIp = null;

						String serverServiceCode = getVmServiceCode(vendor);
						String eipServiceCode = getEipServiceCode(vendor);
						String volumeServiceCode = getVolumeServiceCode(vendor);

						// 根据平台获取浮动IP
						if (CloudProvider.ALIYUN.name().equals(server.getVendorType())) {
							List<ElasticIp> elasticIps = elasticIpRepository.listByIid(server.getInstanceId(),
									server.getVendorId());
							if (!ListTool.isEmpty(elasticIps)) {
								elasticIp = elasticIps.get(0);
								eip = 1;
							}
						} else if (CloudProvider.HUAWEI.name().equals(server.getVendorType())) {
							elasticIp = elasticIpRepository.queryByAllocationId(server.getInstanceId());
							if (null != elasticIp) {
								eip = 1;
							}
						} else if (CloudProvider.TENCENT.name().equals(server.getVendorType())
								|| CloudProvider.QCLOUD.name().equals(server.getVendorType())) {
							floatingIp = floatingIpRepository.listByInstanceId(server.getInstanceId(),
									server.getVendorId());
							if (null != floatingIp) {
								eip = 1;
							}
						} else {
							floatingIp = floatingIpRepository.listByServerId(server.getInstanceId());
							if (null != floatingIp) {
								eip = 1;
							}
						}

						List<Volume> volumes = volumeRepository.listByServerId(server.getId());
						List<Snapshot> snapshots = new ArrayList<>();
						if (!ListTool.isEmpty(volumes)) {
							Long volumeCount = 0L;
							for (Volume volume : volumes) {
								volumeCount += 1;
								// 磁盘总量
								Integer size = volume.getSize();
								if (null != size) {
									disk = disk + size;
								}
								// 磁盘的快照
								List<Snapshot> volumeSnapshots = snapshotRepository.listByVolumeId(volume.getId());
								if(!ListTool.isEmpty(volumeSnapshots)) {
									snapshots.addAll(volumeSnapshots);
								}
							}
							if (!CloudProvider.VMWARE.name().equals(server.getVendorType())) {
								quotas.add(new ResourceQuota(volumeServiceCode, volumeCount));
							}
						}
						if(!ListTool.isEmpty(snapshots)) {
							quotas.add(new ResourceQuota("meta.snapshot", Long.valueOf(snapshots.size())));
						}
						quotas.add(new ResourceQuota("meta.cpu", Long.valueOf(cpu)));
						quotas.add(new ResourceQuota("meta.mem", memory.longValue()));
						quotas.add(new ResourceQuota("meta.disk", Long.valueOf(disk)));
						quotas.add(new ResourceQuota(serverServiceCode, 1L));
						if (eip != 0) {
							quotas.add(new ResourceQuota(eipServiceCode, Long.valueOf(eip)));
						}
						// 更新配额
						result = cosInternalService.updateQuotas(quotas, Action.Order, tenantId);
						Assert.isTrue(result.isSuccess(), result.getMessage());
						// 生成虚拟机订单
						BocloudResult createOrder = resourceOrderService.createOrder(vendor.getId(), serverServiceCode,
								tenantId, userId, true, projectId);
						if(createOrder.isFailed()) {
							// 回滚配额
							callback(orders, items, tenantId, quotas);
							return createOrder;
						}
						ServiceOrder vmOrder = JSONObject.parseObject(JSONObject.toJSONString(createOrder.getData()), ServiceOrder.class);
						if (null == vmOrder) {
							// 回滚配额
							callback(orders, items, tenantId, quotas);
							return new BocloudResult(false, "分配虚拟机发生错误：订单数据异常");
						}
						orders.add(vmOrder);
						result = assignServer(vendor, server, userId, tenantId, projectId, items, vmOrder.getId(),
								serverServiceCode);
						if (result.isFailed()) {
							// 回收虚拟机
							recycleServer(server, vendor, context, false);
							callback(orders, items, tenantId, quotas);
							return new BocloudResult(false, "分配虚拟机失败：" + result.getMessage());
						}
						// 磁盘
						if (!ListTool.isEmpty(volumes)) {
							result = assignVolume(vendor, userId, tenantId, projectId, volumes, items, vmOrder.getId(),
									volumeServiceCode);
							if (result.isFailed()) {
								// 回收虚拟机
								recycleServer(server, vendor, context, false);
								// 更新云硬盘
								recycleVolume(volumes, context, false);
								callback(orders, items, tenantId, quotas);
								return new BocloudResult(false, "分配虚拟机失败：" + result.getMessage());
							}
						}
						if (!ListTool.isEmpty(snapshots)) {
							result = assignSnapshot(userId, tenantId, projectId, snapshots);
							if (result.isFailed()) {
								// 回收虚拟机
								recycleServer(server, vendor, context, false);
								// 更新云硬盘
								recycleVolume(volumes, context, false);
								recycleSnapshot(snapshots, context, false);
								callback(orders, items, tenantId, quotas);
								return new BocloudResult(false, "分配虚拟机失败：" + result.getMessage());
							}
						}
						// 浮动IP
						if (null != floatingIp) {
							// 生成虚拟机订单
							
							BocloudResult createFipOrder = resourceOrderService.createOrder(vendor.getId(), eipServiceCode,
									tenantId, userId, true, projectId);
							if(createFipOrder.isFailed()) {
								// 更新虚拟机
								recycleServer(server, vendor, context, false);
								// 更新云硬盘
								recycleVolume(volumes, context, false);
								recycleSnapshot(snapshots, context, false);
								callback(orders, items, tenantId, quotas);
								return createFipOrder;
							}
							ServiceOrder fipOrder = JSONObject.parseObject(JSONObject.toJSONString(createFipOrder.getData()), ServiceOrder.class);
							if (null == fipOrder) {
								// 更新虚拟机
								recycleServer(server, vendor, context, false);
								// 更新云硬盘
								recycleVolume(volumes, context, false);
								recycleSnapshot(snapshots, context, false);
								callback(orders, items, tenantId, quotas);
								return new BocloudResult(false, "分配虚拟机发生错误：订单生成失败");
							}
							orders.add(fipOrder);
							result = assignFloatingIp(vendor, userId, tenantId, projectId, floatingIp, items,
									fipOrder.getId(), eipServiceCode);
							if (result.isFailed()) {
								// 更新虚拟机
								recycleServer(server, vendor, context, false);
								// 更新云硬盘
								recycleVolume(volumes, context, false);
								// 回收浮动IP
								recycleFloatingIp(floatingIp, context, false);
								recycleSnapshot(snapshots, context, false);
								callback(orders, items, tenantId, quotas);
								return new BocloudResult(false, "分配虚拟机失败：" + result.getMessage());
							}
						}
						if (null != elasticIp) {
							// 生成虚拟机订单
							
							BocloudResult createElasticIpOrder = resourceOrderService.createOrder(vendor.getId(), eipServiceCode,
									tenantId, userId, true, projectId);
							if(createElasticIpOrder.isFailed()) {
								callback(orders, items, tenantId, quotas);
								// 更新虚拟机
								recycleServer(server, vendor, context, false);
								// 更新云硬盘
								recycleVolume(volumes, context, false);
								recycleSnapshot(snapshots, context, false);
								return createElasticIpOrder;
							}
							ServiceOrder fipOrder = JSONObject.parseObject(JSONObject.toJSONString(createElasticIpOrder.getData()), ServiceOrder.class);
							if (null == fipOrder) {
								callback(orders, items, tenantId, quotas);
								// 更新虚拟机
								recycleServer(server, vendor, context, false);
								// 更新云硬盘
								recycleVolume(volumes, context, false);
								recycleSnapshot(snapshots, context, false);
								return new BocloudResult(false, "分配虚拟机发生错误：订单生成失败");
							}
							orders.add(fipOrder);
							result = assignElasticIp(vendor, userId, tenantId, projectId, elasticIp, items,
									fipOrder.getId(), eipServiceCode);
							if (result.isFailed()) {
								// 更新虚拟机
								recycleServer(server, vendor, context, false);
								// 更新云硬盘
								recycleVolume(volumes, context, false);
								recycleSnapshot(snapshots, context, false);
								// 回收浮动IP
								recycleElasticIp(elasticIp, context, false);
								callback(orders, items, tenantId, quotas);
								return new BocloudResult(false, "分配虚拟机失败：" + result.getMessage());
							}
						}
					} catch (Exception e) {
						logger.error("Get error message：{}", e);
						return new BocloudResult(false, e.getMessage());
					}
					break;
				case Storage:
					Volume volume = volumeRepository.query(id);
					if (null == volume) {
						return new BocloudResult(false, "云硬盘不存在");
					}
					vendor = cloudVendorRepository.query(volume.getVendorId());
					Assert.notNull(vendor, "云平台不存在");
					String storageServiceCode = getVolumeServiceCode(vendor);
					quotas.add(new ResourceQuota("meta.disk", Long.valueOf(volume.getSize())));
					quotas.add(new ResourceQuota(storageServiceCode, 1L));
					String snapshotServiceCode = "meta.snapshot";
					List<Snapshot> snapshots = snapshotRepository.listByVolumeId(id);
					if(!ListTool.isEmpty(snapshots)) {
						quotas.add(new ResourceQuota(snapshotServiceCode, Long.valueOf(snapshots.size())));
					}
					result = cosInternalService.updateQuotas(quotas, Action.Order, tenantId);
					Assert.isTrue(result.isSuccess(), result.getMessage());
					List<Volume> volumes = Lists.newArrayList();
					volumes.add(volume);
					// 生成虚拟机订单
					BocloudResult createDiskOrder = resourceOrderService.createOrder(vendor.getId(), storageServiceCode,
							tenantId, userId, true, projectId);
					if(createDiskOrder.isFailed()) {
						// 更新云硬盘
						recycleVolume(volumes, context, false);
						callback(orders, items, tenantId, quotas);
						return createDiskOrder;
					}
					ServiceOrder diskOrder = JSONObject.parseObject(JSONObject.toJSONString(createDiskOrder.getData()), ServiceOrder.class);
					if (null == diskOrder) {
						// 更新云硬盘
						recycleVolume(volumes, context, false);
						callback(orders, items, tenantId, quotas);
						return new BocloudResult(false, "分配云硬盘失败");
					}
					orders.add(diskOrder);
					result = assignVolume(vendor, userId, tenantId, projectId, volumes, items, diskOrder.getId(),
							storageServiceCode);
					if (result.isFailed()) {
						// 更新云硬盘
						recycleVolume(volumes, context, false);
						callback(orders, items, tenantId, quotas);
						return new BocloudResult(false, "分配云硬盘失败：" + result.getMessage());
					}
					if (!ListTool.isEmpty(snapshots)) {
						result = assignSnapshot(userId, tenantId, projectId, snapshots);
						if (result.isFailed()) {
							// 更新云硬盘
							recycleVolume(volumes, context, false);
							// 回收云快照
							recycleSnapshot(snapshots, context, false);
							callback(orders, items, tenantId, quotas);
							return new BocloudResult(false, "分配云硬盘失败：" + result.getMessage());
						}
					}
					break;
				case Vpc:
					path = Vpc.class.getSimpleName() + "_" + id;
					try (BocloudACLock lock = lockFactory.getACLock(path)) {
						Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
						Vpc vpc = vpcRepository.query(id);
						Assert.notNull(vpc, "VPC数据不存在");
						vendor = cloudVendorRepository.query(vpc.getVendorId());
						Assert.notNull(vendor, "云平台不存在");

						String vpcServiceCode = getVpcServiceCode(vendor);
						quotas.add(new ResourceQuota(vpcServiceCode, 1L));
						result = cosInternalService.updateQuotas(quotas, Action.Order, tenantId);
						if(result.isFailed()) {
							if (CloudProvider.OPENSTACK.name().equals(vendor.getType())) {
								vpcRepository.delete(id);
							}
							return result;
						}
						
						BocloudResult createVpcOrder = resourceOrderService.createOrder(vpc.getVendorId(), vpcServiceCode, tenantId, userId,
								null, projectId);
						if(createVpcOrder.isFailed()) {
							callback(orders, items, tenantId, quotas);
							return createVpcOrder;
						}
						ServiceOrder vpcOrder = JSONObject.parseObject(JSONObject.toJSONString(createVpcOrder.getData()), ServiceOrder.class);
						if (null == vpcOrder) {
							callback(orders, items, tenantId, quotas);
							return new BocloudResult(false, "VPC分配失败：订单生成失败，请联系管理员");
						}
						orders.add(vpcOrder);
						result = assignVpc(vendor, userId, tenantId, projectId, vpc, items, vpcOrder.getId(),
								vpcServiceCode);
						if (result.isFailed()) {
							// 回收VPC
							recycleVpc(vpc, context);
							callback(orders, items, tenantId, quotas);
							if (CloudProvider.OPENSTACK.name().equals(vendor.getType())) {
								vpcRepository.delete(id);
							}
							return new BocloudResult(false, "分配VPC失败：" + result.getMessage());
						}
						// 如果当前网络所属的项目与租户没有关联关系 将该项目授权给租户
						if (CloudProvider.OPENSTACK.name().equals(vendor.getType())) {
							Long networkId = vpc.getNetworkId();
							Network network = networkRepository.query(networkId);
							if (null != network) {
								Boolean shared = network.getShared() == null ? false : network.getShared();
								if (!shared) {
									TenantProvider tenantProvider = tenantProviderRepository.query(vendor.getId(),
											tenantId);
									OSTenant osTenant = osTenantRepository.getByTenantUuid(network.getTenantUuid(),
											vendor.getId());
									if (null == tenantProvider && null != osTenant) {
										tenantProvider = new TenantProvider(tenantId, vendor.getId());
										tenantProvider.setProjectName(osTenant.getName());
										tenantProviderRepository.save(tenantProvider);
										osTenant.setTenantId(tenantId);
										osTenantRepository.update(osTenant);
									}
								}
								TenantNetwork entity = new TenantNetwork();
								entity.setNetworkId(networkId);
								entity.setTenantId(tenantId);
								entity.setVendorId(network.getVendorId());
								tenantNetworkRepository.save(entity);
								network.setTenantId(tenantId);
								networkRepository.update(network);
							}
						}
						// 如果当前VPC属于阿里云 则自动将vpc下的安全组分配过去
						if (CloudProvider.ALIYUN.name().equals(vendor.getType())) {
							List<SecurityGroup> securityGroups = securityGroupRepository.listByVpcId(vpc.getId(), null);
							if (!ListTool.isEmpty(securityGroups)) {
								List<Long> securityGroupIds = securityGroups.stream().map(SecurityGroup::getId)
										.collect(Collectors.toList());
								object.put("ids", securityGroupIds);
								object.put("resourceCategory", ResourceCategory.SecurityGroup);
								this.assign(object, ResourceCategory.SecurityGroup, context);
							}
						}
					} catch (Exception e) {
						logger.error("Get error message：{}", e);
						return new BocloudResult(false, e.getMessage());
					}
					break;
				case Network:
					path = Network.class.getSimpleName() + "_" + id;
					try (BocloudACLock lock = lockFactory.getACLock(path)) {
						Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
						Network network = networkRepository.query(id);
						Assert.notNull(network, "网络数据不存在");
						vendor = cloudVendorRepository.query(network.getVendorId());
						Assert.notNull(vendor, "云平台不存在");

						Vpc vpc = new Vpc();
						vpc.setVendorId(network.getVendorId());
						vpc.setRegionId(network.getRegionId());
						vpc.setExpiredTime(DateTools.stringToDateTime("2099-12-31 00:00:00"));
						// 自服务需要用到
						vpc.setOwnerId(userId);
						vpc.setMenderId(userId);
						vpc.setCatalog(Catalog.User);
						vpc.setTenantId(tenantId);
						vpc.setProjectId(projectId);
						vpc.setName(network.getName());
						vpc.setNetworkId(network.getId());
						vpcRepository.save(vpc);

						List<Long> vpcIds = new ArrayList<>();
						vpcIds.add(vpc.getId());
						object.put("ids", vpcIds);
						object.put("resourceCategory", ResourceCategory.Vpc);
						BocloudResult assign = this.assign(object, ResourceCategory.Vpc, context);
						if(assign.isFailed()) {
							return assign;
						}
					} catch (Exception e) {
						logger.error("Get error message：{}", e);
						return new BocloudResult(false, e.getMessage());
					}
				case FloatingIp:
					String vendorType = object.getString("vendorType");
					CloudProvider cloudProvider = CloudProvider.valueOf(vendorType);
					FloatingIp floatingIp = null;
					ElasticIp elasticIp = null;
					if (CloudProvider.ALIYUN == cloudProvider || CloudProvider.HUAWEI == cloudProvider
							|| CloudProvider.AWS == cloudProvider) {
						elasticIp = elasticIpRepository.query(id);
					} else {
						floatingIp = floatingIpRepository.query(id);
					}
					String eipServiceCode = "";
					// 浮动IP
					if (null != floatingIp) {
						vendor = cloudVendorRepository.query(floatingIp.getVendorId());
						eipServiceCode = getEipServiceCode(vendor);
						quotas.add(new ResourceQuota(eipServiceCode, 1L));
						result = cosInternalService.updateQuotas(quotas, Action.Order, tenantId);
						Assert.isTrue(result.isSuccess(), result.getMessage());
						// 生成虚拟机订单
						
						BocloudResult createVpcOrder = resourceOrderService.createOrder(vendor.getId(), eipServiceCode,
								tenantId, userId, true, projectId);
						if(createVpcOrder.isFailed()) {
							return createVpcOrder;
						}
						ServiceOrder fipOrder = JSONObject.parseObject(JSONObject.toJSONString(createVpcOrder.getData()), ServiceOrder.class);
						if (null == fipOrder) {
							return new BocloudResult(false, "分配浮动IP发生错误：订单生成失败");
						}
						orders.add(fipOrder);
						result = assignFloatingIp(vendor, userId, tenantId, projectId, floatingIp, items,
								fipOrder.getId(), eipServiceCode);
						if (result.isFailed()) {
							callback(orders, items, tenantId, quotas);
							return new BocloudResult(false, "分配浮动IP失败：" + result.getMessage());
						}
					}
					if (null != elasticIp) {
						vendor = cloudVendorRepository.query(elasticIp.getVendorId());
						eipServiceCode = getEipServiceCode(vendor);
						quotas.add(new ResourceQuota(eipServiceCode, 1L));
						result = cosInternalService.updateQuotas(quotas, Action.Order, tenantId);
						Assert.isTrue(result.isSuccess(), result.getMessage());
						// 生成虚拟机订单
						BocloudResult createFipOrder = resourceOrderService.createOrder(vendor.getId(), eipServiceCode,
								tenantId, userId, true, projectId);
						if(createFipOrder.isFailed()) {
							return createFipOrder;
						}
						ServiceOrder fipOrder = JSONObject.parseObject(JSONObject.toJSONString(createFipOrder.getData()), ServiceOrder.class);
						if (null == fipOrder) {
							return new BocloudResult(false, "分配浮动IP发生错误：订单生成失败");
						}
						orders.add(fipOrder);
						result = assignElasticIp(vendor, userId, tenantId, projectId, elasticIp, items,
								fipOrder.getId(), eipServiceCode);
						if (result.isFailed()) {
							callback(orders, items, tenantId, quotas);
							return new BocloudResult(false, "分配浮动IP失败：" + result.getMessage());
						}
					}
					break;
				case LoadBalance:
					path = LoadBalancer.class.getSimpleName() + "_" + id;
					try (BocloudACLock lock = lockFactory.getACLock(path)) {
						Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
						LoadBalancer loadBalancer = loadBalancerRepository.query(id);
						Assert.notNull(loadBalancer, "负载均衡数据不存在");
						vendor = cloudVendorRepository.query(loadBalancer.getVendorId());
						Assert.notNull(vendor, "云平台不存在");

						String slbServiceCode = getSlbServiceCode(vendor);
						quotas.add(new ResourceQuota(slbServiceCode, 1L));
						result = cosInternalService.updateQuotas(quotas, Action.Order, tenantId);
						Assert.isTrue(result.isSuccess(), result.getMessage());
						
						BocloudResult createSlbOrder = resourceOrderService.createOrder(id, slbServiceCode, tenantId, userId,
								null, projectId);
						if(createSlbOrder.isFailed()) {
							return createSlbOrder;
						}
						ServiceOrder slbOrder = JSONObject.parseObject(JSONObject.toJSONString(createSlbOrder.getData()), ServiceOrder.class);
						if (null == slbOrder) {
							return new BocloudResult(false, "负载均衡分配失败：订单生成失败，请联系管理员");
						}
						orders.add(slbOrder);
						result = assignLoadBalance(vendor, userId, tenantId, projectId, loadBalancer, items,
								slbOrder.getId(), slbServiceCode);
						if (result.isFailed()) {
							// 回收lb
							callback(orders, items, tenantId, quotas);
							return new BocloudResult(false, "负载均衡分配失败：" + result.getMessage());
						}
					} catch (Exception e) {
						logger.error("Get error message：{}", e);
						return new BocloudResult(false, e.getMessage());
					}
					break;
				case SecurityGroup:
					path = SecurityGroup.class.getSimpleName() + "_" + id;
					try (BocloudACLock lock = lockFactory.getACLock(path)) {
						Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
						SecurityGroup securityGroup = securityGroupRepository.query(id);
						Assert.notNull(securityGroup, "安全组数据不存在");
						vendor = cloudVendorRepository.query(securityGroup.getVendorId());
						Assert.notNull(vendor, "云平台不存在");
						CloudProvider segCloudProvider = CloudProvider.valueOf(vendor.getType());
						if (CloudProvider.OPENSTACK == segCloudProvider) {
							TenantProvider provider = tenantProviderRepository.query(vendor.getId(), tenantId);
							if (null == provider
									|| !provider.getTenantUuid().equalsIgnoreCase(securityGroup.getTenantUuid())) {
								return new BocloudResult<>(false,
										"安全组【" + securityGroup.getName() + "】不允许分配给该租户，所属项目不同");
							}
						}
						securityGroup.setTenantId(tenantId);
						securityGroupRepository.update(securityGroup);
					} catch (Exception e) {
						logger.error("Get error message：{}", e);
						return new BocloudResult(false, e.getMessage());
					}
					break;
				case Snapshot:
					path = Snapshot.class.getSimpleName() + "_" + id;
					try (BocloudACLock lock = lockFactory.getACLock(path)) {
						Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
						Snapshot snapshot = snapshotRepository.query(id);
						Assert.notNull(snapshot, "快照数据不存在");
						vendor = cloudVendorRepository.query(snapshot.getVendorId());
						Assert.notNull(vendor, "云平台不存在");

						quotas.add(new ResourceQuota("meta.snapshot", 1L));
						result = cosInternalService.updateQuotas(quotas, Action.Order, tenantId);
						Assert.isTrue(result.isSuccess(), result.getMessage());
						if (result.isFailed()) {
							return new BocloudResult(false, "快照分配失败：" + result.getMessage());
						}
						snapshot.setTenantId(tenantId);
						snapshot.setExpiredTime(DateTools.stringToDateTime("2099-12-31 00:00:00"));
						snapshot.setCatalog(Catalog.User);
						snapshot.setMenderId(userId);
						snapshot.setOwnerId(userId);
						snapshot.setProjectId(projectId);
						snapshotRepository.update(snapshot);
					} catch (Exception e) {
						logger.error("Get error message：{}", e);
						return new BocloudResult(false, e.getMessage());
					}
					break;
				default:
					return new BocloudResult(false, "暂不支持");
				}
				// 处理成功订单
				resourceOrderService.processOrderStatus(orders, ChargeCommon.ResourceStatus.ready);
				// 处理订单明细
				resourceOrderService.processOrderItemStatus(items, OrderItemStatus.OpenedSuccess);
			}
			return new BocloudResult(true, "资源分配成功");
		} catch (Exception e) {
			logger.error("Get error message：{}", e);
			return new BocloudResult(false, "资源分配失败： " + e.getMessage());
		}
	}

	private BocloudResult assignLoadBalance(CloudVendor vendor, Long userId, Long tenantId, Long projectId,
			LoadBalancer loadBalancer, List<OrderItem> items, Long orderId, String slbServiceCode) {
		// 下单
		BocloudResult<OrderItem> itemResult = resourceOrderService.createLoadBalancerItem(orderId, slbServiceCode,
				loadBalancer, vendor);
		if (itemResult.isFailed()) {
			return new BocloudResult(false, itemResult.getMessage());
		}
		OrderItem item = itemResult.getData();
		items.add(item);

		loadBalancer.setExpiredTime(DateTools.stringToDateTime("2099-12-31 00:00:00"));
		loadBalancer.setCatalog(Catalog.User);
		loadBalancer.setTenantId(tenantId);
		loadBalancer.setMenderId(userId);
		loadBalancer.setOwnerId(userId);
		loadBalancer.setProjectId(projectId);
		loadBalancer.setUuid(item.getSn());
		loadBalancerRepository.update(loadBalancer);
		return new BocloudResult(true, "负载均衡分配成功");
	}

	private void recycleElasticIp(ElasticIp elasticIp, RequestContext context, Boolean isNotice) throws Exception {
		if (null != elasticIp) {
			String orderItemSn = elasticIp.getUuid();
			elasticIp.setUuid(null);
			elasticIp.setProjectId(0L);
			elasticIp.setTenantId(0L);
			elasticIp.setMenderId(0L);
			elasticIp.setOwnerId(0L);
			elasticIp.setExpiredTime(null);
			elasticIp.setGmtModify(new Date());
			elasticIpRepository.update(elasticIp);
			objectRelationRepository.deleteByRid(elasticIp.getId(), ResourceCategory.FloatingIp.name());
			
			if(isNotice) {
				OrderMessage orderMessage = new OrderMessage(orderItemSn, OrderMessage.Operation.Cancelation,
						OrderItemStatus.UnsubscribeSuccess, null, "浮动IP退订成功", null, null, new ArrayList<>(),
						ResourceCategory.FloatingIp.name(), context);
				orderMessage.setCategory(ResourceCategory.FloatingIp.name());
				amqpTemplate.convertAndSend("resource.result.queue", orderMessage);
			}
		}

	}

	private BocloudResult assignElasticIp(CloudVendor vendor, Long userId, Long tenantId, Long projectId,
			ElasticIp elasticIp, List<OrderItem> items, Long orderId, String eipServiceCode) {
		// 下单
		BocloudResult<OrderItem> itemResult = resourceOrderService.createElasticIpItem(orderId, eipServiceCode,
				elasticIp, vendor);
		if (itemResult.isFailed()) {
			return new BocloudResult(false, itemResult.getMessage());
		}
		OrderItem item = itemResult.getData();
		items.add(item);

		elasticIp.setExpiredTime(DateTools.stringToDateTime("2099-12-31 00:00:00"));
		elasticIp.setCatalog(Catalog.User);
		elasticIp.setTenantId(tenantId);
		elasticIp.setMenderId(userId);
		elasticIp.setOwnerId(userId);
		elasticIp.setProjectId(projectId);
		elasticIp.setUuid(item.getSn());
		elasticIpRepository.update(elasticIp);
		return new BocloudResult(true, "浮动IP分配成功");
	}

	private void recycleVpc(Vpc vpc, RequestContext context) {
		if (null != vpc) {
			String orderItemSn = vpc.getUuid();
			vpc.setExpiredTime(null);
			vpc.setCatalog(Catalog.Manager);
			vpc.setTenantId(0L);
			vpc.setMenderId(0L);
			vpc.setOwnerId(0L);
			vpc.setProjectId(0L);
			vpc.setUuid(null);
			vpc.setPoolGroupId(null);
			vpcRepository.update(vpc);
			OrderMessage orderMessage = new OrderMessage(orderItemSn, OrderMessage.Operation.Cancelation,
					OrderItemStatus.UnsubscribeSuccess, null, "资源回收成功", null, null, new ArrayList<>(),
					ResourceCategory.Vpc.name(), context);
			orderMessage.setCategory(ResourceCategory.Vpc.name());
			amqpTemplate.convertAndSend("resource.result.queue", orderMessage);
		}
	}

	private BocloudResult assignVpc(CloudVendor vendor, Long userId, Long tenantId, Long projectId, Vpc vpc,
			List<OrderItem> items, Long orderId, String serviceCode) {
		// 下单
		BocloudResult<OrderItem> createVpcItem = resourceOrderService.createVpcItem(orderId, serviceCode, vpc, vendor);

		if (createVpcItem.isFailed()) {
			return new BocloudResult(false, createVpcItem.getMessage());
		}
		OrderItem item = createVpcItem.getData();
		items.add(item);
		vpc.setExpiredTime(DateTools.stringToDateTime("2099-12-31 00:00:00"));
		vpc.setCatalog(Catalog.User);
		vpc.setTenantId(tenantId);
		vpc.setMenderId(userId);
		vpc.setOwnerId(userId);
		vpc.setProjectId(projectId);
		vpc.setUuid(item.getSn());

		String regionId = null;
		CloudProvider cloudProvider = CloudProvider.valueOf(vendor.getType());
		switch (cloudProvider) {
		case ALIYUN:
		case HUAWEI:
		case TENCENT:
		case AWS:
		case TCE:
		case QCLOUD:
			regionId = vpc.getRegionId();
			break;
		default:
			break;
		}
		// 获取资源池ID
		BocloudResult poolGroupResult = getPoolGroupId(vendor.getId(), tenantId, regionId);
		if (poolGroupResult.isSuccess()) {
			vpc.setPoolGroupId(Long.parseLong(poolGroupResult.getData().toString()));
		}
		vpcRepository.update(vpc);
		return new BocloudResult(true, "VPC分配成功");

	}

	/**
	 * 回滚
	 *
	 * @param orders
	 * @param items
	 * @param projectId
	 * @param quotas
	 */
	private void callback(List<ServiceOrder> orders, List<OrderItem> items, Long tenantId, List<ResourceQuota> quotas) {
		// 回滚配额
		cosInternalService.updateQuotas(quotas, Action.Callback, tenantId);
		quotas.clear();
		// 处理订单
		resourceOrderService.processOrderStatus(orders, ChargeCommon.ResourceStatus.failed);
		orders.clear();
		// 处理订单明细
		resourceOrderService.processOrderItemStatus(items, OrderItemStatus.OpenedFailure);
		items.clear();
	}

	/**
	 * 云硬盘服务类型
	 *
	 * @param vendor
	 * @return
	 */
	private String getVolumeServiceCode(CloudVendor vendor) {
		String serviceCode = vendor.getType().toLowerCase() + ".standard.volume";
		switch (CloudProvider.valueOf(vendor.getType())) {
		case OPENSTACK:
		case ALIYUN:
			break;
		case VMWARE:
			serviceCode = "vmware.storage.disk";
			break;
		default:
			return serviceCode;
		}
		return serviceCode;
	}

	private String getSlbServiceCode(CloudVendor vendor) {
		String slbServiceCode = "network." + vendor.getType().toLowerCase() + ".slb";
		return slbServiceCode;
	}

	private String getVpcServiceCode(CloudVendor vendor) {
		String vpcServiceCode = vendor.getType().toLowerCase() + ".standard.vpc";
		return vpcServiceCode;
	}

	private String getEipServiceCode(CloudVendor vendor) {
		String eipServiceCode = "network." + vendor.getType().toLowerCase() + ".eip";
		if (CloudProvider.OPENSTACK.name().equalsIgnoreCase(vendor.getType())) {
			eipServiceCode = CloudProvider.OPENSTACK.name().toLowerCase() + ".standard.eip";
		}
		return eipServiceCode;
	}

	private String getVmServiceCode(CloudVendor vendor) {
		String vmServiceCode = vendor.getType().toLowerCase() + ".standard.server";
		return vmServiceCode;
	}

	@Override
	public BocloudResult reclaim(ResourceAssignParam vmAssignParam, ResourceCategory category, RequestContext context) {
		// 资源ID
		List<Long> serverIds = vmAssignParam.getIds();
		if (ListTool.isEmpty(serverIds)) {
			return new BocloudResult<>(false, "无资源可回收");
		}
		try {
			for (Long id : serverIds) {
				String path = null;
				List<Volume> volumes = Lists.newArrayList();
				List<Snapshot> snaps = Lists.newArrayList();
				List<ResourceQuota> quotas = new ArrayList<>();
				switch (category) {
				case Computer:
					path = CloudServer.class.getSimpleName() + "_" + id;
					try (BocloudACLock lock = lockFactory.getACLock(path)) {
						Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
						CloudServer server = cloudServerRepository.query(id);
						Assert.notNull(server, "虚拟机不存在");
						CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
						Assert.notNull(vendor, "云平台不存在");

						Integer cpu = server.getCpu();
						BigDecimal memory = server.getMemory();
						Integer disk = 0;
						Integer eip = 0;
						FloatingIp floatingIp = null;
						ElasticIp elasticIp = null;

						String serverServiceCode = getVmServiceCode(vendor);
						String eipServiceCode = getEipServiceCode(vendor);
						String volumeServiceCode = getVolumeServiceCode(vendor);

						// 根据平台获取浮动IP
						if (CloudProvider.ALIYUN.name().equals(server.getVendorType())) {
							List<ElasticIp> elasticIps = elasticIpRepository.listByIid(server.getInstanceId(),
									server.getVendorId());
							if (!ListTool.isEmpty(elasticIps)) {
								elasticIp = elasticIps.get(0);
								eip = 1;
							}
						} else if (CloudProvider.HUAWEI.name().equals(server.getVendorType())) {
							elasticIp = elasticIpRepository.queryByAllocationId(server.getInstanceId());
							if (null != elasticIp) {
								eip = 1;
							}
						} else if (CloudProvider.TENCENT.name().equals(server.getVendorType())
								|| CloudProvider.QCLOUD.name().equals(server.getVendorType())) {
							floatingIp = floatingIpRepository.listByInstanceId(server.getInstanceId(),
									server.getVendorId());
							if (null != floatingIp) {
								eip = 1;
							}
						} else {
							floatingIp = floatingIpRepository.listByServerId(server.getInstanceId());
							if (null != floatingIp) {
								eip = 1;
							}
						}
						volumes = volumeRepository.listByServerId(server.getId());
						List<Snapshot> snapshots = new ArrayList<>();
						if (!ListTool.isEmpty(volumes)) {
							Long volumeCount = 0L;
							for (Volume volume : volumes) {
								volumeCount += 1;
								//
								Integer size = volume.getSize();
								if (null != size) {
									disk = disk + size;
								}
								//磁盘的快照
								List<Snapshot> volumeSnapshots = snapshotRepository.listByVolumeId(volume.getId());
								if(!ListTool.isEmpty(volumeSnapshots)) {
									snapshots.addAll(volumeSnapshots);
								}
							}
							if (!CloudProvider.VMWARE.name().equals(server.getVendorType())) {
								quotas.add(new ResourceQuota(volumeServiceCode, volumeCount));
							}
						}
						quotas.add(new ResourceQuota("meta.cpu", Long.valueOf(cpu)));
						quotas.add(new ResourceQuota("meta.mem", memory.longValue()));
						quotas.add(new ResourceQuota("meta.disk", Long.valueOf(disk)));
						quotas.add(new ResourceQuota(serverServiceCode, 1L));
						if (eip != 0) {
							quotas.add(new ResourceQuota(eipServiceCode, Long.valueOf(eip)));
						}
						// 回收虚拟机
						recycleServer(server, vendor, context, true);
						recycleVolume(volumes, context, true);
						recycleFloatingIp(floatingIp, context, true);
						recycleElasticIp(elasticIp, context, true);
						recycleSnapshot(snapshots, context, true);
					} catch (Exception e) {
						logger.error("Get error message：", e);
						return new BocloudResult(false, e.getMessage());
					}
					break;
				case Storage:
					path = Volume.class.getSimpleName() + "_" + id;
					try (BocloudACLock lock = lockFactory.getACLock(path)) {
						Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
						Volume volume = volumeRepository.query(id);
						Assert.notNull(volume, "云硬盘不存在");
						volumes.add(volume);
						recycleVolume(volumes, context, true);
						List<Snapshot> snapshots = snapshotRepository.listByVolumeId(volume.getId());
						recycleSnapshot(snapshots, context, true);
					} catch (Exception e) {
						logger.error("Get error message：", e);
						return new BocloudResult(false, e.getMessage());
					}
					break;
				case Vpc:
					path = Vpc.class.getSimpleName() + "_" + id;
					try (BocloudACLock lock = lockFactory.getACLock(path)) {
						Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
						Vpc vpc = vpcRepository.query(id);
						Assert.notNull(vpc, "VPC不存在");
						Long vendorId = vpc.getVendorId();
						Long tenantId = vpc.getTenantId();
						CloudVendor vpcCloudVendor = cloudVendorRepository.query(vendorId);
						Assert.notNull(vpcCloudVendor, "云平台不存在");
						String vpcServiceCode = getVpcServiceCode(vpcCloudVendor);
						quotas.add(new ResourceQuota(vpcServiceCode, Long.valueOf(1)));
						recycleVpc(vpc, context);
						// 如果当前VPC对应的网络为op 且网络类型为非共享 则删除该VPC
						if (CloudProvider.OPENSTACK.name().equals(vpcCloudVendor.getType())) {
							Long networkId = vpc.getNetworkId();
							Network network = networkRepository.query(networkId);
							vpcRepository.delete(id);
							tenantNetworkRepository.delete(networkId, tenantId, vendorId);
							network.setTenantId(0L);
							networkRepository.update(network);
						}
						// 如果当前VPC属于阿里云 回收时自动回收vpc下的安全组
						if (CloudProvider.ALIYUN.name().equals(vpcCloudVendor.getType())) {
							List<SecurityGroup> securityGroups = securityGroupRepository.listByVpcId(vpc.getId(), null);
							if (!ListTool.isEmpty(securityGroups)) {
								List<Long> securityGroupIds = securityGroups.stream().map(SecurityGroup::getId)
										.collect(Collectors.toList());
								ResourceAssignParam networkAssignParam = new ResourceAssignParam();
								networkAssignParam.setIds(securityGroupIds);
								networkAssignParam.setResourceCategory(ResourceCategory.SecurityGroup);
								this.reclaim(networkAssignParam, ResourceCategory.SecurityGroup, context);
							}
						}
					} catch (Exception e) {
						logger.error("Get error message：", e);
						return new BocloudResult(false, e.getMessage());
					}
					break;
				case Network:
					path = Network.class.getSimpleName() + "_" + id;
					try (BocloudACLock lock = lockFactory.getACLock(path)) {
						Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
						Network network = networkRepository.query(id);
						Assert.notNull(network, "网络不存在");
						CloudVendor vpcCloudVendor = cloudVendorRepository.query(network.getVendorId());
						Assert.notNull(vpcCloudVendor, "云平台不存在");
						List<Vpc> vpcs = vpcRepository.listByNetworkId(network.getId());
						if (ListTool.isEmpty(vpcs)) {
							tenantNetworkRepository.deleteByNetworkId(network.getId());
							network.setTenantId(0L);
							networkRepository.update(network);
							return new BocloudResult(true, "回收成功！");
						}
						List<Long> vpcIds = new ArrayList<Long>();
						if (network.getShared()) {
							List<Long> tenantIds = vmAssignParam.getTenantIds();
							if (ListTool.isEmpty(tenantIds)) {
								return new BocloudResult<>(true, "资源回收成功");
							}
							List<Vpc> tenantVpcs = new ArrayList<Vpc>();
							for (Vpc vpc : vpcs) {
								if (tenantIds.contains(vpc.getTenantId())) {
									tenantVpcs.add(vpc);
								}
							}
							vpcIds = tenantVpcs.stream().map(Vpc::getId).collect(Collectors.toList());
						} else {
							vpcIds = vpcs.stream().map(Vpc::getId).collect(Collectors.toList());
						}
						if (!ListTool.isEmpty(vpcIds)) {
							ResourceAssignParam networkAssignParam = new ResourceAssignParam();
							networkAssignParam.setIds(vpcIds);
							networkAssignParam.setResourceCategory(ResourceCategory.Vpc);
							this.reclaim(networkAssignParam, ResourceCategory.Vpc, context);
						}
					} catch (Exception e) {
						logger.error("Get error message：", e);
						return new BocloudResult(false, e.getMessage());
					}
					break;
				case FloatingIp:
					String vendorType = vmAssignParam.getVendorType();
					CloudProvider cloudProvider = CloudProvider.valueOf(vendorType);
					FloatingIp floatingIp = null;
					ElasticIp elasticIp = null;
					if (CloudProvider.ALIYUN == cloudProvider || CloudProvider.HUAWEI == cloudProvider
							|| CloudProvider.AWS == cloudProvider) {
						elasticIp = elasticIpRepository.query(id);
					} else {
						floatingIp = floatingIpRepository.query(id);
					}
					recycleElasticIp(elasticIp, context, true);
					recycleFloatingIp(floatingIp, context, true);
					break;
				case LoadBalance:
					path = LoadBalancer.class.getSimpleName() + "_" + id;
					try (BocloudACLock lock = lockFactory.getACLock(path)) {
						Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
						LoadBalancer loadBalancer = loadBalancerRepository.query(id);
						Assert.notNull(loadBalancer, "负载均衡不存在");
						CloudVendor slbCloudVendor = cloudVendorRepository.query(loadBalancer.getVendorId());
						Assert.notNull(slbCloudVendor, "云平台不存在");
						String slbServiceCode = getSlbServiceCode(slbCloudVendor);
						quotas.add(new ResourceQuota(slbServiceCode, 1L));
						recycleLoadBalancer(loadBalancer, context);
					} catch (Exception e) {
						logger.error("Get error message：", e);
						return new BocloudResult(false, e.getMessage());
					}
					break;
				case SecurityGroup:
					path = SecurityGroup.class.getSimpleName() + "_" + id;
					try (BocloudACLock lock = lockFactory.getACLock(path)) {
						Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
						SecurityGroup securityGroup = securityGroupRepository.query(id);
						Assert.notNull(securityGroup, "安全组数据不存在");
						CloudVendor segCloudVendor = cloudVendorRepository.query(securityGroup.getVendorId());
						Assert.notNull(segCloudVendor, "云平台不存在");
						securityGroup.setTenantId(0L);
						securityGroup.setMenderId(0L);
						securityGroupRepository.update(securityGroup);
					} catch (Exception e) {
						logger.error("Get error message：{}", e);
						return new BocloudResult(false, e.getMessage());
					}
					break;
				case Snapshot:
					path = LoadBalancer.class.getSimpleName() + "_" + id;
					try (BocloudACLock lock = lockFactory.getACLock(path)) {
						Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
						Snapshot snapshot = snapshotRepository.query(id);
						Assert.notNull(snapshot, "快照数据不存在");
						Long tenantId = snapshot.getTenantId();
						CloudVendor snapCloudVendor = cloudVendorRepository.query(snapshot.getVendorId());
						Assert.notNull(snapCloudVendor, "云平台不存在");
						quotas.add(new ResourceQuota("meta.snapshot", 1L));
						snapshot.setTenantId(0L);
						snapshot.setProjectId(0L);
						snapshot.setCatalog(Catalog.Manager);
						snapshot.setMenderId(0L);
						snapshot.setOwnerId(0L);
						snapshotRepository.update(snapshot);
						BocloudResult snapshotUpdateQuotas = cosInternalService.updateQuotas(quotas, Action.Callback,
								tenantId);
						if (snapshotUpdateQuotas.isFailed()) {
							return snapshotUpdateQuotas;
						}
					} catch (Exception e) {
						logger.error("Get error message：", e);
						return new BocloudResult(false, e.getMessage());
					}
					break;
				default:
					break;
				}
			}
		} catch (Exception e) {
			logger.error("Get error message：", e);
			return new BocloudResult(false, "资源回收失败");
		}
		return new BocloudResult(true, "资源回收成功");
	}

	private void recycleLoadBalancer(LoadBalancer loadBalancer, RequestContext context) {
		if (null != loadBalancer) {
			String orderItemSn = loadBalancer.getUuid();
			loadBalancer.setExpiredTime(null);
			loadBalancer.setCatalog(Catalog.Manager);
			loadBalancer.setTenantId(0L);
			loadBalancer.setMenderId(0L);
			loadBalancer.setOwnerId(0L);
			loadBalancer.setProjectId(0L);
			loadBalancer.setUuid(null);
			loadBalancerRepository.update(loadBalancer);

			OrderMessage orderMessage = new OrderMessage(orderItemSn, OrderMessage.Operation.Cancelation,
					OrderItemStatus.UnsubscribeSuccess, null, "负载均衡退订成功", null, null, new ArrayList<>(),
					ResourceCategory.LoadBalance.name(), context);
			orderMessage.setCategory(ResourceCategory.LoadBalance.name());
			amqpTemplate.convertAndSend("resource.result.queue", orderMessage);
		}
	}

	/**
	 * 分配虚拟机
	 *
	 * @param vendor
	 * @param server
	 * @param userId
	 * @param tenantId
	 * @param projectId
	 * @param items
	 * @param orderId
	 * @return
	 * @throws Exception
	 */
	private BocloudResult assignServer(CloudVendor vendor, CloudServer server, Long userId, Long tenantId,
			Long projectId, List<OrderItem> items, Long orderId, String serverServiceCode) throws Exception {
		// 下单
		BocloudResult<OrderItem> itemResult = resourceOrderService.createServerItem(orderId, serverServiceCode, server,
				vendor);
		if (itemResult.isFailed()) {
			return new BocloudResult(false, itemResult.getMessage());
		}
		OrderItem item = itemResult.getData();
		items.add(item);

		Date expiredTime = server.getExpiredTime();
		if (null == expiredTime) {
			server.setExpiredTime(DateTools.stringToDateTime("2099-12-31 00:00:00"));
		}
		// 自服务需要用到
		server.setOwnerId(userId);
		server.setMenderId(userId);
		server.setCatalog(Catalog.User);
		server.setTenantId(tenantId);
		server.setRecycle(false);
		server.setProjectId(projectId);
		server.setUuid(item.getSn());
		// 获取资源池ID
		BocloudResult poolGroupResult = getPoolGroupId(vendor.getId(), tenantId, null);
		if (poolGroupResult.isSuccess()) {
			server.setPoolGroupId(Long.parseLong(poolGroupResult.getData().toString()));
		}
		cloudServerRepository.update(server);
		List<String> ips = Lists.newArrayList();
		String vendorType = server.getVendorType();
		switch (CloudProvider.valueOf(vendorType)) {
		case VMWARE:
			if (!StringUtils.isEmpty(server.getPrivateIps())) {
				List<JSONObject> objects = JSONObject.parseArray(server.getPrivateIps(), JSONObject.class);
				for (JSONObject jsonObject : objects) {
					if (StringUtils.isEmpty(jsonObject.getString("address"))) {
						continue;
					}
					ips.add(jsonObject.getString("address"));
				}
			}
			break;
		default:
			break;
		}
		Resource resource = resourceRepository.query(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
				server.getId());
		if (null == resource) {
			resource = new Resource(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(), server.getId(),
					JSONObject.toJSONString(ips), server.getOsCategory(), server.getVendorId());
			resource.preSave(server.getName(), server.getStatus(), 1L, tenantId);
			resource.setInventory(JSONObject.toJSONString(server));
			resourceRepository.save(resource);
		} else {
			resource.setTenantId(tenantId);
			resource.setMenderId(userId);
			resource.setOwnerId(userId);
			resource.setGmtModify(new Date());
			resourceRepository.update(resource);
		}
		return new BocloudResult(true, "分配虚拟机成功");
	}

	public BocloudResult getPoolGroupId(Long vendorId, Long tenantId, String regionId) {
		try {
			JSONObject object = new JSONObject();
			object.put("condition", "listByVendorId");
			object.put("vendorId", vendorId);
			object.put("tenantId", tenantId);
			object.put("regionId", regionId);
			BocloudResult tenantPoolGroupResult = resourcePoolService.condition(null, object.toJSONString(), null);
			if (tenantPoolGroupResult.isFailed()) {
				return new BocloudResult<>(false, "当前租户未绑定相关平台资源池");
			}
			PoolGroup findGroup = (PoolGroup) tenantPoolGroupResult.getData();
			if (null == findGroup) {
				return new BocloudResult<>(false, "当前租户未绑定相关平台资源池");
			}
			return new BocloudResult<>(true, findGroup.getId(), "查询成功");
		} catch (Exception e) {
			logger.error("查询租户资源池异常: " + e.getMessage());
			return new BocloudResult<>(false, "当前租户未绑定相关平台资源池");
		}
	}

	/**
	 * 回收分配给租户的虚拟机
	 *
	 * @param server
	 * @param vendor
	 * @param context
	 * @throws Exception
	 */
	private void recycleServer(CloudServer server, CloudVendor vendor, RequestContext context, Boolean isNotice) throws Exception {
		objectRelationRepository.deleteByRid(server.getId(), ResourceCategory.Computer.name());
		List<String> ips = Lists.newArrayList();
		String vendorType = server.getVendorType();
		switch (CloudProvider.valueOf(vendorType)) {
		case VMWARE:
			if (!StringUtils.isEmpty(server.getPrivateIps())) {
				List<JSONObject> objects = JSONObject.parseArray(server.getPrivateIps(), JSONObject.class);
				for (JSONObject jsonObject : objects) {
					if (StringUtils.isEmpty(jsonObject.getString("address"))) {
						continue;
					}
					ips.add(jsonObject.getString("address"));
				}
			}
		default:
			break;
		}
		Resource resource = resourceRepository.query(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
				server.getId());
		if (null == resource) {
			resource = new Resource(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(), server.getId(),
					JSONObject.toJSONString(ips), server.getOsCategory(), vendor.getId());
			resource.preSave(server.getName(), server.getStatus(), server.getCreatorId(), 0L);
			resource.setInventory(JSONObject.toJSONString(server));
			resourceRepository.save(resource);
		} else {
			resource.setTenantId(0L);
			resource.setOwnerId(context.getTarget());
			resource.setMenderId(context.getTarget());
			resource.setGmtModify(new Date());
			resourceRepository.update(resource);
		}
		Boolean recycle = server.getRecycle();
		String orderItemSn = server.getUuid();
		server.setUuid(null);
		server.setExpiredTime(null);
		server.setTenantId(0L);
		server.setOwnerId(0L);
		server.setProjectId(0L);
		server.setCatalog(Catalog.Manager);
		server.setMenderId(0L);
		server.setGmtModify(new Date());
		server.setPoolGroupId(null);
		server.setRecycle(false);
		cloudServerRepository.update(server);
		if(isNotice) {
			OrderMessage message = new OrderMessage(orderItemSn, Operation.Cancelation, OrderItemStatus.UnsubscribeSuccess,
					null, "资源回收成功", null, null, null, ResourceCategory.Computer.name(), context);
			message.setCategory(ResourceCategory.Computer.name());
			amqpTemplate.convertAndSend("resource.result.queue", message);
		}

		if (null != recycle && recycle) {
			cosInternalService.recycle(orderItemSn);
		}
		// 终止订单
		// cosInternalService.updateItemStatus(server.getUuid(),
		// OrderItemStatus.Termination.name());
	}

	/**
	 * 分配云硬盘给租户用户
	 *
	 * @param vendor
	 * @param userId
	 * @param tenantId
	 * @param projectId
	 * @param volumes
	 * @param items
	 * @param orderId
	 * @param serviceCode
	 * @return
	 * @throws Exception
	 */
	private BocloudResult assignVolume(CloudVendor vendor, Long userId, Long tenantId, Long projectId,
			List<Volume> volumes, List<OrderItem> items, Long orderId, String serviceCode) throws Exception {
		if (ListTool.isEmpty(volumes)) {
			return new BocloudResult<>(true, "云硬盘分配成功");
		}
		for (Volume volume : volumes) {
			// 下单
			BocloudResult<OrderItem> itemResult = resourceOrderService.createVolumeItem(orderId, serviceCode, volume,
					vendor);
			if (itemResult.isFailed()) {
				return new BocloudResult(false, itemResult.getMessage());
			}
			OrderItem item = itemResult.getData();
			items.add(item);
			volume.setExpiredTime(DateTools.stringToDateTime("2099-12-31 00:00:00"));
			// 自服务需要用到
			volume.setOwnerId(userId);
			volume.setMenderId(userId);
			volume.setCatalog(Catalog.User);
			volume.setTenantId(tenantId);
			volume.setProjectId(projectId);
			volume.setSkuId(item.getSkuId());
			volume.setUuid(item.getSn());
			volumeRepository.update(volume);
		}

		return new BocloudResult(true, "云硬盘分配成功");
	}

	/**
	 * 回收分配给租户的云硬盘
	 *
	 * @param volumes
	 * @param context
	 * @throws Exception
	 */
	private void recycleVolume(List<Volume> volumes, RequestContext context, Boolean isNotice) throws Exception {
		if (ListTool.isEmpty(volumes)) {
			return;
		}
		OrderMessage volumeOrderMessage = new OrderMessage(null, Operation.Cancelation,
				OrderItemStatus.UnsubscribeSuccess, null, "资源回收成功", null, null, new ArrayList<>(),
				ResourceCategory.Storage.name(), context);
		volumeOrderMessage.setCategory(ResourceCategory.Storage.name());
		for (Volume volume : volumes) {
			String orderItemSn = volume.getUuid();
			volume.setTenantId(0L);
			volume.setProjectId(0L);
			volume.setCatalog(Catalog.Manager);
			volume.setMenderId(0L);
			volume.setOwnerId(0L);
			volume.setGmtModify(new Date());
			volume.setExpiredTime(null);
			volume.setUuid(null);
			volumeRepository.update(volume);
			objectRelationRepository.deleteByRid(volume.getId(), ResourceCategory.Storage.name());
			if(isNotice) {
				volumeOrderMessage.setSn(orderItemSn);
				amqpTemplate.convertAndSend("resource.result.queue", volumeOrderMessage);
			}
		}
	}

	/**
	 * 镜像分配
	 *
	 * @param userId
	 * @param tenantId
	 * @param projectId
	 * @param image
	 * @return
	 * @throws Exception
	 */
	public BocloudResult assignImage(Long userId, Long tenantId, Long projectId, Image image) throws Exception {
		ObjectRelation relation = objectRelationRepository.get(image.getId(), ResourceCategory.Image.name());
		Calendar calendar = Calendar.getInstance();
		if (null == relation) {
			relation = new ObjectRelation(userId, image.getId(), false, ResourceCategory.Image.name(),
					Catalog.User.name(), 0);
			calendar.setTime(DateTools.stringToDateTime("2099-12-31 00:00:00"));
			relation.setExpiredTime(calendar.getTime());
			objectRelationRepository.save(relation);
		} else {
			relation.setTarget(userId);
			calendar.setTime(DateTools.stringToDateTime("2099-12-31 00:00:00"));
			relation.setExpiredTime(calendar.getTime());
			objectRelationRepository.update(relation);
		}
		image.setTenantId(tenantId);
		image.setProjectId(projectId);
		imageRepository.update(image);
		return new BocloudResult(true, "镜像分配成功");
	}

	/**
	 * 分配云快照给租户用户
	 *
	 * @param userId
	 * @param tenantId
	 * @param projectId
	 * @param snapshots
	 * @return
	 * @throws Exception
	 */
	private BocloudResult assignSnapshot(Long userId, Long tenantId, Long projectId, List<Snapshot> snapshots)
			throws Exception {
		if (!ListTool.isEmpty(snapshots)) {
			Date stringToDateTime = DateTools.stringToDateTime("2099-12-31 00:00:00");
			for (Snapshot snapshot : snapshots) {
				snapshot.setExpiredTime(stringToDateTime);
				snapshot.setTenantId(tenantId);
				snapshot.setProjectId(projectId);
				snapshot.setCatalog(Catalog.User);
				snapshot.setMenderId(userId);
				snapshot.setOwnerId(userId);
				snapshotRepository.update(snapshot);
			}
		}
		return new BocloudResult(true, "云快照分配成功");
	}

	/**
	 * 回收分配给租户的云快照
	 *
	 * @param snapshots
	 * @param context
	 * @throws Exception
	 */
	private void recycleSnapshot(List<Snapshot> snapshots, RequestContext context, Boolean isNotice) throws Exception {
		if (!ListTool.isEmpty(snapshots)) {
			for (Snapshot snapshot : snapshots) {
				Long tenantId = snapshot.getTenantId();
				snapshot.setTenantId(0L);
				snapshot.setProjectId(0L);
				snapshot.setOwnerId(0L);
				snapshot.setCatalog(Catalog.Manager);
				snapshot.setMenderId(0L);
				snapshot.setGmtModify(new Date());
				snapshot.setExpiredTime(null);
				snapshotRepository.update(snapshot);

				if(null != tenantId && 0 != tenantId && isNotice) {
					List<ResourceQuota> quotas = new ArrayList<>();
					String snapshotServiceCode = "meta.snapshot";
					quotas.add(new ResourceQuota(snapshotServiceCode, Long.valueOf(1)));
					cosInternalService.updateQuotas(quotas, Action.Callback, tenantId);
				}

			}
		}
	}

	/**
	 * 分配网络接口给租户用户
	 *
	 * @param userId
	 * @param tenantId
	 * @param projectId
	 * @return
	 * @throws Exception
	 */
	private BocloudResult assignNetworkInterface(Long userId, Long tenantId, Long projectId,
			List<NetworkInterface> networkInterfaces) throws Exception {
		if (!ListTool.isEmpty(networkInterfaces)) {
			for (NetworkInterface networkInterface : networkInterfaces) {
				networkInterface.setTenantId(tenantId);
				networkInterface.setProjectId(projectId);
				networkInterfaceRepository.update(networkInterface);
			}
		}
		return new BocloudResult(true, "网络接口分配成功");
	}

	/**
	 * 回收分配给租户的网络接口
	 *
	 * @param networkInterfaces
	 * @param menderId
	 * @throws Exception
	 */
	private void recycleNetworkInterface(List<NetworkInterface> networkInterfaces, Long menderId) throws Exception {
		if (!ListTool.isEmpty(networkInterfaces)) {
			for (NetworkInterface networkInterface : networkInterfaces) {
				networkInterface.setTenantId(0L);
				networkInterface.setProjectId(0L);
				networkInterface.setMenderId(menderId);
				networkInterface.setGmtModify(new Date());
				networkInterfaceRepository.update(networkInterface);
			}
		}
	}

	/**
	 * 分配浮动IP给租户用户
	 *
	 * @param vendor
	 * @param userId
	 * @param tenantId
	 * @param projectId
	 * @param floatingIp
	 * @param items
	 * @param orderId
	 * @param eipServiceCode
	 * @return
	 * @throws Exception
	 */
	private BocloudResult assignFloatingIp(CloudVendor vendor, Long userId, Long tenantId, Long projectId,
			FloatingIp floatingIp, List<OrderItem> items, Long orderId, String eipServiceCode) throws Exception {
		// 下单
		BocloudResult<OrderItem> itemResult = resourceOrderService.createFipItem(orderId, eipServiceCode, floatingIp,
				vendor);
		if (itemResult.isFailed()) {
			return new BocloudResult(false, itemResult.getMessage());
		}
		OrderItem item = itemResult.getData();
		items.add(item);
		floatingIp.setExpiredTime(DateTools.stringToDateTime("2099-12-31 00:00:00"));
		floatingIp.setOwnerId(userId);
		floatingIp.setMenderId(userId);
		floatingIp.setProjectId(projectId);
		floatingIp.setTenantId(tenantId);
		floatingIp.setCatalog(Catalog.User);
		floatingIp.setUuid(item.getSn());
		floatingIpRepository.update(floatingIp);
		return new BocloudResult(true, "浮动IP分配成功");
	}

	/**
	 * 回收分配给项目的浮动IP
	 *
	 * @param floatingIp
	 * @param context
	 * @throws Exception
	 */
	private void recycleFloatingIp(FloatingIp floatingIp, RequestContext context, Boolean isNotice) throws Exception {
		if (null != floatingIp) {
			String orderItemSn = floatingIp.getUuid();
			floatingIp.setProjectId(0L);
			floatingIp.setTenantId(0L);
			floatingIp.setOwnerId(0L);
			floatingIp.setMenderId(0L);
			floatingIp.setExpiredTime(null);
			floatingIp.setGmtModify(new Date());
			floatingIp.setUuid(null);
			floatingIpRepository.update(floatingIp);
			objectRelationRepository.deleteByRid(floatingIp.getId(), ResourceCategory.FloatingIp.name());
			if (isNotice) {
				OrderMessage orderMessage = new OrderMessage(orderItemSn, OrderMessage.Operation.Cancelation,
						OrderItemStatus.UnsubscribeSuccess, null, "浮动IP退订成功", null, null, new ArrayList<>(),
						ResourceCategory.FloatingIp.name(), context);
				orderMessage.setCategory(ResourceCategory.FloatingIp.name());
				amqpTemplate.convertAndSend("resource.result.queue", orderMessage);
			}
		}
	}

}
