package com.bocloud.ims.service.resource;

import static com.bocloud.ims.service.utils.DateUtils.timeToList;
import static java.util.stream.Collectors.groupingBy;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.compute.ServerDriver;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.entity.enums.ModuleCode;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.CloudServerBean;
import com.bocloud.cmp.model.ElasticIpGenericParam;
import com.bocloud.cmp.model.ImageModel;
import com.bocloud.cmp.model.NetcardOperation;
import com.bocloud.cmp.model.NetworkCardModel;
import com.bocloud.cmp.model.NetworkModel;
import com.bocloud.cmp.model.NicAdapterModel;
import com.bocloud.cmp.model.OSMigrateModel;
import com.bocloud.cmp.model.ServerModel;
import com.bocloud.cmp.model.SnapshotModel;
import com.bocloud.cmp.model.VMBean;
import com.bocloud.cmp.model.VolumeModel;
import com.bocloud.cmp.model.common.ChargeResultTrend;
import com.bocloud.cmp.model.common.ChargeTrendData;
import com.bocloud.cmp.model.common.OrderMessage;
import com.bocloud.cmp.model.common.QuotaBean;
import com.bocloud.cmp.vm.model.BatchSnapshotParam;
import com.bocloud.cmp.vm.model.VmBatchOperationParam;
import com.bocloud.cmp.vm.model.VmDeleteParam;
import com.bocloud.cmp.vm.model.VmGenericParam;
import com.bocloud.cmp.vm.model.VmSnapshotParam;
import com.bocloud.common.encrypt.AESEncrptor;
import com.bocloud.common.encrypt.Encryptor;
import com.bocloud.common.enums.ResourceCatalog;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.GridBean;
import com.bocloud.common.model.OperateResult;
import com.bocloud.common.model.OperateResult.OperateCategory;
import com.bocloud.common.model.Pager;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.model.Sign;
import com.bocloud.common.model.RequestContext.Catalog;
import com.bocloud.common.model.SimpleBean;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.IDFactory;
import com.bocloud.common.utils.JSONTools;
import com.bocloud.common.utils.ListTool;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.common.enums.ServerAction;
import com.bocloud.ims.entity.common.Business;
import com.bocloud.ims.entity.common.Dictionary;
import com.bocloud.ims.entity.common.Project;
import com.bocloud.ims.entity.common.Tenant;
import com.bocloud.ims.entity.common.User;
import com.bocloud.ims.entity.resource.CloudServer;
import com.bocloud.ims.entity.resource.CloudServerBusiness;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.Cluster;
import com.bocloud.ims.entity.resource.DataStore;
import com.bocloud.ims.entity.resource.ElasticIp;
import com.bocloud.ims.entity.resource.Flavor;
import com.bocloud.ims.entity.resource.FloatingIp;
import com.bocloud.ims.entity.resource.Image;
import com.bocloud.ims.entity.resource.Ip;
import com.bocloud.ims.entity.resource.Keypair;
import com.bocloud.ims.entity.resource.Label;
import com.bocloud.ims.entity.resource.LbMember;
import com.bocloud.ims.entity.resource.LbPool;
import com.bocloud.ims.entity.resource.LoadBalancer;
import com.bocloud.ims.entity.resource.Network;
import com.bocloud.ims.entity.resource.NetworkCard;
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.PortGroup;
import com.bocloud.ims.entity.resource.Region;
import com.bocloud.ims.entity.resource.Resource;
import com.bocloud.ims.entity.resource.ResourceEvent;
import com.bocloud.ims.entity.resource.ResourceGroup;
import com.bocloud.ims.entity.resource.ResourceQuota;
import com.bocloud.ims.entity.resource.SecurityGroup;
import com.bocloud.ims.entity.resource.Server;
import com.bocloud.ims.entity.resource.ServerKeypair;
import com.bocloud.ims.entity.resource.ServerLabel;
import com.bocloud.ims.entity.resource.Snapshot;
import com.bocloud.ims.entity.resource.SnapshotTask;
import com.bocloud.ims.entity.resource.StoreHost;
import com.bocloud.ims.entity.resource.Subnet;
import com.bocloud.ims.entity.resource.Switcher;
import com.bocloud.ims.entity.resource.Vdc;
import com.bocloud.ims.entity.resource.VmResourcePool;
import com.bocloud.ims.entity.resource.Volume;
import com.bocloud.ims.entity.resource.Zone;
import com.bocloud.ims.entity.resource.ResourceQuota.Action;
import com.bocloud.ims.entity.resource.hmc.HmcPartition;
import com.bocloud.ims.entity.resource.manageone.ManageOneAccount;
import com.bocloud.ims.interfaces.manageone.ManageOneAccountService;
import com.bocloud.ims.interfaces.resource.CloudServerService;
import com.bocloud.ims.interfaces.resource.ElasticIpService;
import com.bocloud.ims.interfaces.resource.NameRuleService;
import com.bocloud.ims.interfaces.resource.VMApplyService;
import com.bocloud.ims.interfaces.resource.VMExtendService;
import com.bocloud.ims.interfaces.resource.hmc.HmcPartitionService;
import com.bocloud.ims.interfaces.scheduler.SnapshotTaskService;
import com.bocloud.ims.repository.resource.CloudServerBusinessRepository;
import com.bocloud.ims.repository.resource.CloudServerRepository;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.ClusterRepository;
import com.bocloud.ims.repository.resource.DataStoreRepository;
import com.bocloud.ims.repository.resource.DictionaryRepository;
import com.bocloud.ims.repository.resource.ElasticIpRepository;
import com.bocloud.ims.repository.resource.FlavorRepository;
import com.bocloud.ims.repository.resource.FloatingIpRepository;
import com.bocloud.ims.repository.resource.ImageRepository;
import com.bocloud.ims.repository.resource.IpPoolRepository;
import com.bocloud.ims.repository.resource.IpRepository;
import com.bocloud.ims.repository.resource.KeypairRepository;
import com.bocloud.ims.repository.resource.LabelRepository;
import com.bocloud.ims.repository.resource.LbMemberRepository;
import com.bocloud.ims.repository.resource.LbPoolRepository;
import com.bocloud.ims.repository.resource.LoadBalancerRepository;
import com.bocloud.ims.repository.resource.NetworkCardRepository;
import com.bocloud.ims.repository.resource.NetworkHostRepository;
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.PortGroupRepository;
import com.bocloud.ims.repository.resource.RegionRepository;
import com.bocloud.ims.repository.resource.ResourceEventRepository;
import com.bocloud.ims.repository.resource.ResourceGroupRepository;
import com.bocloud.ims.repository.resource.ResourcePoolRepository;
import com.bocloud.ims.repository.resource.ResourceRepository;
import com.bocloud.ims.repository.resource.SecurityGroupRepository;
import com.bocloud.ims.repository.resource.ServerKeypairRepository;
import com.bocloud.ims.repository.resource.ServerLabelRepository;
import com.bocloud.ims.repository.resource.ServerRepository;
import com.bocloud.ims.repository.resource.SnapshotRepository;
import com.bocloud.ims.repository.resource.SnapshotTaskRepository;
import com.bocloud.ims.repository.resource.StoreHostRepository;
import com.bocloud.ims.repository.resource.SubnetRepository;
import com.bocloud.ims.repository.resource.SwitcherRepository;
import com.bocloud.ims.repository.resource.VdcRepository;
import com.bocloud.ims.repository.resource.VolumeRepository;
import com.bocloud.ims.repository.resource.ZoneRepository;
import com.bocloud.ims.repository.resource.hmc.HmcPartitionRepository;
import com.bocloud.ims.service.builder.ServerBuilder;
import com.bocloud.ims.service.builder.VMServerBuilder;
import com.bocloud.ims.service.internal.CosInternalService;
import com.bocloud.ims.service.internal.SmsBusinessService;
import com.bocloud.ims.service.internal.SmsProjectService;
import com.bocloud.ims.service.internal.SmsTenantService;
import com.bocloud.ims.service.internal.SmsUserService;
import com.bocloud.ims.service.internal.worker.LvmService;
import com.bocloud.ims.service.model.ProcessResult;
import com.bocloud.ims.service.model.cmdb.CmdbInfo;
import com.bocloud.ims.service.model.cmdb.CmdbModel;
import com.bocloud.ims.service.thread.CloudServerCreateTask;
import com.bocloud.ims.service.thread.CloudServerParam;
import com.bocloud.ims.service.utils.CmdbInfoConvertor;
import com.bocloud.ims.service.utils.DateUtils;
import com.bocloud.ims.service.utils.IpRangeUtil;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
import com.bocloud.ims.service.utils.ServerOperationHelper;
import com.bocloud.ims.service.utils.SyncVmwareUtils;
import com.bocloud.nms.enums.OrderItemStatus;
import com.bocloud.service.core.CurrentService;
import com.bocloud.service.license.LicenseDaemon;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * 虚拟机实现类
 *
 * @author DZG
 * @since V1.0 2016年9月12日
 */
@Service("cloudServerService")
public class CloudServerServiceImpl implements CloudServerService, InitializingBean {

	private static Logger logger = LoggerFactory.getLogger(CloudServerServiceImpl.class);
	private static OperateCategory operateCategory = OperateResult.OperateCategory.ResourceEvent;
	private LinkedBlockingQueue<CloudServerParam> serverDelayCreateQueue = null;
	private static String[] PUBLIC_CLOUDS = new String[] { CloudProvider.FUSIONCLOUD.name(),
			CloudProvider.MANAGEONE.name(), CloudProvider.QCLOUD.name(), CloudProvider.AZURE.name(),
			CloudProvider.HUAWEI.name(), CloudProvider.TENCENT.name(), CloudProvider.JDCLOUD.name(),
			CloudProvider.ALIYUN.name(), CloudProvider.AWS.name() };
	@Autowired
	private HmcPartitionService hmcPartitionService;
	@Autowired
	private HmcPartitionRepository hmcPartitionRepository;
	@Autowired
	private SmsProjectService smsProjectService;
	@Autowired
	private FlavorRepository flavorRepository;
	@Autowired
	private FloatingIpRepository floatingIpRepository;
	@Autowired
	private SecurityGroupRepository securityGroupRepository;
	@Autowired
	private RegionRepository regionRepository;
	@Autowired
	private ZoneRepository zoneRepository;
	@Autowired
	private KeypairRepository keyPairRepository;
	@Autowired
	private ServerKeypairRepository serverKeyPairRepository;
	@Autowired
	private OSTenantRepository osTenantRepository;
	@Autowired
	private CloudServerRepository cloudServerRepository;
	@Autowired
	private CloudVendorRepository cloudVendorRepository;
	@Autowired
	private ResourceEventRepository resourceEventRepository;
	@Autowired
	private ImageRepository imageRepository;
	@Autowired
	private DataStoreRepository dataStoreRepository;
	@Autowired
	private ServerRepository serverRepository;
	@Autowired
	private LockFactory lockFactory;
	@Autowired
	private SnapshotRepository snapshotRepository;
	@Autowired
	private ServerDriver serverDriver;
	@Autowired
	private StoreHostRepository storeHostRepository;
	@Autowired
	private NetworkRepository networkRepository;
	@Autowired
	private PortGroupRepository portGroupRepository;
	@Autowired
	private SwitcherRepository switcherRepository;
	@Autowired
	private NetworkHostRepository networkHostRepository;
	@Autowired
	private NetworkCardRepository networkCardRepository;
	@Autowired
	private ResourceEventPublisher resourceEventPublisher;
	@Autowired
	private ResourceRepository resourceRepository;
	@Autowired
	private IpRepository ipRepository;
	@Autowired
	private IpPoolRepository ipPoolRepository;
	@Autowired
	private ObjectRelationRepository objectRelationRepository;
	@Autowired
	private VolumeRepository volumeRepository;
	@Autowired
	private AmqpTemplate amqpTemplate;
	@Autowired
	private VdcRepository vdcRepository;
	@Autowired
	private ResourcePoolRepository resourcePoolRepository;
	@Autowired
	private ClusterRepository clusterRepository;
	@Autowired
	private DictionaryRepository dictionaryRepository;
	@Autowired
	private NameRuleService nameRuleService;
	@Autowired
	private LabelRepository labelRepository;
	@Autowired
	private ServerLabelRepository serverLabelRepository;
	@Autowired
	private ServerOperationHelper serverOperationHelper;
	@Autowired
	private SnapshotTaskRepository snapshotTaskRepository;
	@Autowired
	private SubnetRepository subnetRepository;
	@Autowired
	private NetworkInterfaceRepository networkInterfaceRepository;
	@Autowired
	private ElasticIpRepository elasticIpRepository;
	@Autowired
	private SmsTenantService smsTenantService;
	@Autowired
	private VMApplyService vmApplyService;
	@Autowired
	private VMExtendService vmExtendService;
	@Autowired
	private ManageOneAccountService accountService;
	@Autowired
	private LvmService lvmService;
	@Autowired
	private SmsUserService smsUserService;
	@Autowired
	private SmsBusinessService smsBusinessService;
	@Autowired
	private ThreadPoolTaskExecutor taskExecutor;
	@Autowired
	private ElasticIpService elasticIpService;
	private final LicenseDaemon licenseDaemon;
	@Autowired
	private CloudServerBusinessRepository serverBusinessRepository;
	@Autowired
	private SnapshotTaskService snapshotTaskService;
	@Autowired
	private LabelServiceImpl labelServiceImpl;
	@Autowired
	private ResourceGroupRepository resourceGroupRepository;
	@Autowired
	private LbPoolRepository lbPoolRepository;
	@Autowired
	private LoadBalancerRepository loadBalancerRepository;
	@Autowired
	private LbMemberRepository lbMemberRepository;
	@Autowired
	private CosInternalService cosInternalService;

	public CloudServerServiceImpl(CurrentService currentService) {
		this.licenseDaemon = LicenseDaemon.instance(currentService);
	}

	@Override
	public BocloudResult<GridBean<CloudServer>> list(Pager pager, RequestContext context) {
		GridBean<CloudServer> gridBean;
		try {
			List<Param> params = Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>());
			Map<String, String> sorter = Optional.ofNullable(pager.getSorter()).orElse(Maps.newHashMap());
			Boolean simple = Optional.ofNullable(pager.getSimple()).orElse(false);
			sorter.put("gmtCreate", Common.ONE);
			Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
			Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);
			Long clusterId = null;
			String labelContent = null;
			for (Param param : params) {
				Map<String, Object> paramMap = param.getParam();
				if (paramMap.containsKey("clusterId")) {
					clusterId = Long.valueOf(paramMap.get("clusterId").toString());
					paramMap.remove("clusterId");
				}
				if (paramMap.containsKey("labelContent")) {
					labelContent = paramMap.get("labelContent").toString();
					paramMap.remove("labelContent");
				}
			}
			int total = 0;
			sorter = Optional.ofNullable(sorter).orElse(new HashMap<>(8));
			sorter.put("gmtCreate", Common.ONE);
			List<CloudServer> list = Lists.newArrayList();
			if (context.getCatalog().equals(Catalog.Tenant)) {
				// 租户能看到 1.属于当前租户的资源 2.租户下所有项目的资源
				List<Project> tenantProjects = smsProjectService.listTenantProjects(context.getTenant());
				List<Long> projectIds = tenantProjects.stream().map(Project::getId).collect(Collectors.toList());
				total = this.cloudServerRepository.count(null, context.getTenant(), projectIds, params, labelContent);
				list = this.cloudServerRepository.list(page, rows, null, context.getTenant(), projectIds, params,
						sorter, labelContent);
				gridBean = new GridBean<>(page, rows, total, list);
			} else if (context.getCatalog().equals(Catalog.User)) {
				// 用户能看到 1.自己申请的资源 2.自己所在的资源可见项目（资源对项目下所有成员可见）下创建的资源 3.自己管理的项目下的资源
				List<Project> userManagerProjects = smsProjectService.listUserManagerProjects(context.getTarget());
				List<Project> visibleProjects = smsProjectService.listUserVisibleProjects(context.getTarget());
				List<Long> projectIds = new ArrayList<>();
				List<Long> userManagerProjectsIds = userManagerProjects.stream().map(Project::getId)
						.collect(Collectors.toList());
				if (!userManagerProjectsIds.isEmpty()) {
					projectIds.addAll(userManagerProjectsIds);
				}
				List<Long> visibleProjectsIds = visibleProjects.stream().map(Project::getId)
						.collect(Collectors.toList());
				if (!visibleProjectsIds.isEmpty()) {
					projectIds.addAll(visibleProjectsIds);
				}
				total = this.cloudServerRepository.count(context.getTarget(), null, projectIds, params, labelContent);
				list = this.cloudServerRepository.list(page, rows, context.getTarget(), null, projectIds, params,
						sorter, labelContent);
				gridBean = new GridBean<>(page, rows, total, list);
			} else {
				// 管理端搜索
				if (null != clusterId) {
					total = this.cloudServerRepository.count(clusterId, params);
					list = this.cloudServerRepository.list(page, rows, clusterId, params, sorter);
					gridBean = new GridBean<>(page, rows, total, list);
				} else if (simple) {
					total = this.cloudServerRepository.count(params, 0L);
					List<SimpleBean> beans = this.cloudServerRepository.list(params, sorter);
					gridBean = new GridBean(1, 1, total, beans);
				} else {
					total = this.cloudServerRepository.vmCount(params, labelContent);
					list = this.cloudServerRepository.list(page, rows, params, sorter, labelContent);
					gridBean = new GridBean<>(page, rows, total, list);
				}
			}
			if (!simple) {
				List<Long> tenantIds = new ArrayList<>();
				List<Long> userIds = new ArrayList<>();
				List<Long> businessIds = new ArrayList<>();
				List<Long> projectIds = new ArrayList<>();
				for (CloudServer cloudServer : list) {
					if (cloudServer.getTenantId() != null) {
						tenantIds.add(cloudServer.getTenantId());
					}
					if (cloudServer.getBusinessId() != null) {
						businessIds.add(cloudServer.getBusinessId());
					}
					if (cloudServer.getProjectId() != null) {
						projectIds.add(cloudServer.getProjectId());
					}
					if (cloudServer.getCreatorId() != null) {
						userIds.add(cloudServer.getCreatorId());
					}
					if (cloudServer.getOwnerId() != null) {
						userIds.add(cloudServer.getOwnerId());
					}
					if (cloudServer.getMenderId() != null) {
						userIds.add(cloudServer.getMenderId());
					}
				}
				Map<Long, String> userMap = smsUserService.listUsersByIds(userIds).stream()
						.collect(Collectors.toMap(User::getId, User::getName));
				Map<Long, String> projectMap = smsProjectService.listProjectsByIds(projectIds).stream()
						.collect(Collectors.toMap(Project::getId, Project::getName));
				Map<Long, String> businessMap = smsBusinessService.listBusinesssByIds(businessIds).stream()
						.collect(Collectors.toMap(Business::getId, Business::getName));
				Map<Long, String> tenantMap = smsTenantService.listTenantsByIds(tenantIds).stream()
						.collect(Collectors.toMap(Tenant::getId, Tenant::getName));
				for (CloudServer server : list) {
					// 设置虚拟机归属信息
					if (server.getTenantId() != null) {
						server.setTenantName(tenantMap.get(server.getTenantId()));
					}
					if (server.getBusinessId() != null) {
						server.setBusinessName(businessMap.get(server.getBusinessId()));
					}
					if (server.getProjectId() != null) {
						server.setProjectName(projectMap.get(server.getProjectId()));
					}
					if (server.getCreatorId() != null) {
						server.setCreatorName(userMap.get(server.getCreatorId()));
					}
					if (server.getOwnerId() != null) {
						server.setOwnerName(userMap.get(server.getOwnerId()));
					}
					if (server.getMenderId() != null) {
						server.setMenderName(userMap.get(server.getMenderId()));
					}
					// 设置主机名称
					Server host = serverRepository.basic(server.getHostId());
					host = Optional.ofNullable(host).orElse(new Server());
					server.setHostName(host.getName());
					server.setClusterName(host.getClusterName());
					server.setVdcName(host.getVdcName());
					server.setDisk((null == server.getDisk() || 0 == server.getDisk()) ? server.getTotalDisks()
							: server.getDisk());
					// 查询是否存在定时快照任务
					server.setHasSnapshotTask(snapshotTaskRepository.hasTask(server.getId()));
					// 设置快照数量
					server.setSnapshotCount(snapshotRepository.count(server.getId()));
					if (!StringUtils.isEmpty(server.getResourceGroup())) {
						String resourceGroupName = dictionaryRepository.getNameByValue(server.getResourceGroup());
						server.setResourceGroupName(resourceGroupName);
					}

					CloudProvider provider = CloudProvider.valueOf(server.getVendorType());
					if (CloudProvider.OPENSTACK == provider || CloudProvider.FUSIONCLOUD == provider
							|| CloudProvider.MANAGEONE == provider) {
						server.setBootFromVolume(
								volumeRepository.isBootFromVolume(server.getId(), server.getVendorId(), true));
						// 设置浮动IP
						FloatingIp floatingIp = floatingIpRepository.getByServerId(server.getId());
						if (null != floatingIp) {
							server.setFipId(floatingIp.getId());
							server.setFloatingIp(floatingIp.getFloatingIpAddress());
							Network network = networkRepository.query(floatingIp.getNetworkId());
							if (null != network) {
								server.setFloatingIpName(network.getName());
							}
						}
					} else if (CloudProvider.VMWARE == provider) {
						Volume volume = volumeRepository.getByServerId(server.getId(), "Hard disk 1");
						if (null != volume) {
							server.setSystemDiskSize(volume.getSize());
						}
					}
					if (CloudProvider.TIANYI == provider || CloudProvider.HUAWEI == provider) {
						FloatingIp floatingIp = floatingIpRepository.getByInstanceId(server.getInstanceId());
						if (null != floatingIp) {
							server.setFipId(floatingIp.getId());
							server.setFloatingIp(floatingIp.getFloatingIpAddress());
						}
					}
					// 国网POC 阿里云
					if (CloudProvider.ALIYUN == provider && !StringUtils.isEmpty(server.getResourceGroupUuid())) {
						ResourceGroup resourceGroup = resourceGroupRepository.getByGroupUuid(server.getVendorId(),
								server.getResourceGroupUuid());
						if (null != resourceGroup) {
							server.setResourceGroupName(resourceGroup.getName());
						}
					}
				}
				gridBean.setRows(list);
			}
			return new BocloudResult<>(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("Query vm list fail:{}", e.getMessage());
			return new BocloudResult<>(false, "查询失败");
		}
	}

	/**
	 * license校验
	 *
	 * @param vendorId
	 * @param pm
	 * @param vm
	 * @return
	 */
	private BocloudResult licenseCheck(Long vendorId, Integer pm, Integer vm) {
		try {
			Integer pmCount = serverRepository.licenseNodeCount() + pm;
			Integer vmCount = 0;
			if (null != vendorId) {
				CloudVendor vendor = cloudVendorRepository.query(vendorId);
				vendor = Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
				// 公有云虚拟机节点4合1,私有云虚拟机节点不计数
				if (Arrays.asList(PUBLIC_CLOUDS).contains(vendor.getType())) {
					vmCount = cloudServerRepository.vendorCount(Arrays.asList(PUBLIC_CLOUDS));
					vmCount += vm;
					vmCount = vmCount % 4 > 0 ? vmCount / 4 + 1 : vmCount / 4;
				}
			}
			List<String> types = Arrays.asList(new String[] { CloudProvider.F5.name() });
			int nodeCount = pmCount + vmCount + cloudVendorRepository.listByTypes(types, null).size();
			if (nodeCount > licenseDaemon.getLicenseContent().getNode()) {
				return new BocloudResult(false, "当前系统节点数（宿主机和虚拟机）已超过license限制，创建虚拟机失败!", "500", "");
			}
			return new BocloudResult(true, "license校验通过");
		} catch (Exception e) {
			logger.error("Get error message：{}", e);
			return new BocloudResult(false, "license校验失败：" + e.getMessage());
		}
	}

	@Override
	public BocloudResult create(VmGenericParam params, RequestContext context) {
		String password = params.getPassword();
		logger.info("虚拟机设置的密码密文：{}", password);
		if (!StringUtils.isEmpty(password)) {
			Encryptor encryptor = new AESEncrptor();
			try {
				password = encryptor.decrypt(password.trim(), null);
				logger.info("虚拟机设置的密码解密：{}", password);
				params.setPassword(password);
			} catch (Exception e) {
				logger.error("Get error message:{}", e);
				return new BocloudResult(false, e.getMessage());
			}
		}
		// 云平台ID
		Long vendorId = params.getVendorId();
		// 创建数量
		Integer count = params.getCount() == null ? 1 : params.getCount();
		// license节点数校验
		BocloudResult licenseResult = this.licenseCheck(vendorId, 0, count);
		if (licenseResult.isFailed()) {
			return licenseResult;
		}
		Long nameRuleId = params.getNameRuleId();
		String name = params.getName();
		String vmHostName = params.getVmHostName();
		List<ProcessResult> results = Lists.newArrayList();
		String path = CloudVendor.class.getSimpleName() + "_" + vendorId + "_SYNC";
		CloudVendor vendor = null;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			if (!lock.acquire(10, TimeUnit.SECONDS)) {
				logger.warn("当前云平台存在同步任务！延迟创建！");
				serverDelayCreateQueue.add(new CloudServerParam("create", params, context));
				return new BocloudResult(true, "任务下发成功！");
			}
			vendor = cloudVendorRepository.query(vendorId);
			vendor = Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
			CloudProvider provider = CloudProvider.valueOf(vendor.getType());
			if (CloudProvider.AWS.name().equals(vendor.getType()) && !StringUtils.isEmpty(params.getManagerIp())) {
				Long subnetId = params.getSubnetId();
				Subnet subnet = subnetRepository.query(subnetId);
				if (null == subnet) {
					return new BocloudResult(false, "子网不存在");
				}
				if (!IpRangeUtil.checkIpInRange(params.getManagerIp(), subnet.getCidr())) {
					return new BocloudResult(false,
							"IP(" + params.getManagerIp() + ")不在子网CIDR(" + subnet.getCidr() + ")范围内");
				}
			}
			VmGenericParam newParams = JSONObject.parseObject(JSONObject.toJSONString(params), VmGenericParam.class);
			newParams.setCreatorId(context.getTarget());
			newParams.setMenderId(context.getTarget());
			newParams.setOwnerId(context.getTarget());
			for (int i = 0; i < count; i++) {
				// 虚拟机名称
				String serverName = "";
				String newVmHostName = "";
				if (null != nameRuleId && 0L != nameRuleId) {
					serverName = serverOperationHelper.generateName(nameRuleId, vendorId, context);
					if (StringUtils.isEmpty(serverName)) {
						for (ProcessResult result : results) {
							// 删除创建失败的虚拟机
							cloudServerRepository.remove(result.getCloudServer().getId(), context.getTarget());
						}
						return new BocloudResult(false, "根据命名规则生成命名时发生错误");
					}
					if (!StringUtils.isEmpty(vmHostName)) {
						newVmHostName = vmHostName + "-" + (i + 1);
					}
				} else if (count == 1) {
					serverName = name;
					newVmHostName = vmHostName;
				} else {
					if (CloudProvider.AZURE == provider) {
						serverName = name + "-" + (i + 1);
						if (!StringUtils.isEmpty(vmHostName)) {
							newVmHostName = vmHostName + "-" + (i + 1);
						}
						newParams.setSystemDiskName(newParams.getSystemDiskName() + "-" + IDFactory.instance().mac());
					} else {
						serverName = name + "_" + (i + 1);
						if (!StringUtils.isEmpty(vmHostName)) {
							newVmHostName = vmHostName + "-" + (i + 1);
						}
					}
				}
				newParams.setName(serverName);
				if (!StringUtils.isEmpty(newVmHostName)) {
					newParams.setVmHostName(newVmHostName);
				}
				BocloudResult<ServerBuilder> builderResult = serverOperationHelper.getProcess(provider, vendor,
						context);
				if (builderResult.isFailed()) {
					return new BocloudResult(false, builderResult.getMessage());
				}
				ServerBuilder process = builderResult.getData();
				BocloudResult<ProcessResult> procResult = serverOperationHelper.prepare(newParams, context, vendor,
						process);
				if (procResult.isFailed()) {
					for (ProcessResult result : results) {
						// 删除创建失败的虚拟机
						cloudServerRepository.remove(result.getCloudServer().getId(), context.getTarget());
					}
					return new BocloudResult(false, procResult.getMessage());
				}
				ProcessResult proc = procResult.getData();
				proc.setServerBuilder(process);
				results.add(proc);
			}
		} catch (Exception e) {
			logger.error("Get error message：", e);
			return new BocloudResult(false, "虚拟机创建失败");
		}
		CloudVendor finalVendor = vendor;
		new Thread(() -> {
			logger.info("Batch create virtual machine start...");
			for (ProcessResult result : results) {
				taskExecutor.submit(() -> {
					CloudServer preServer = result.getCloudServer();
					BocloudResult<CloudServer> bocloudResult = serverOperationHelper.builder(preServer.getVendorType(),
							vendorId, preServer, context, result.getServerBuilder(), null);
					// 保存标签 适配所有虚机
                    if (bocloudResult.isSuccess()) {
                        CloudServer cloudServer = bocloudResult.getData();
                        String resourceLabel = params.getResourceLabel();
                        if (!StringUtils.isEmpty(resourceLabel)) {
                            labelServiceImpl.saveServerLabel(cloudServer.getId(), "VM", cloudServer.getVendorId(),
                                resourceLabel, context);
                        }
                    }
					if (bocloudResult.isSuccess()
							&& CloudProvider.AWS.name().equalsIgnoreCase(preServer.getVendorType())) {
						CloudServer cloudServer = bocloudResult.getData();
						try {
							if (params.getHasIpv6()) {
								JSONArray privateIps = JSONArray.parseArray(cloudServer.getPrivateIps());
								Subnet subnet = subnetRepository.query(params.getSubnetId());
								String ipv6Cidr = subnet.getIpv6Cidr();
								logger.info("ipv6Cidr:" + ipv6Cidr);
								List<NetworkInterface> interfaces = networkInterfaceRepository.listByServerId(vendorId,
										cloudServer.getId());
								if (ListTool.isEmpty(interfaces)) {
									logger.error("虚机网络接口不存在");
									resourceEventPublisher.send(new OperateResult(false, "虚机网络接口不存在",
											finalVendor.getType().toLowerCase() + ".vm",
											MapTools.simpleMap(Common.VENDORID, vendorId), operateCategory, context));
								} else {
									String ipV6Address = ipv6Cidr.substring(0, ipv6Cidr.indexOf("/") - 1)
											+ privateIps.getString(0);
									ipV6Address = ipV6Address.replaceAll("\\.", ":");
									BocloudResult assignIpv6Result = new BocloudResult(false, "Ipv6分配失败");
									int num = 0;
									while (num < 60) {
										Thread.sleep(5000);
										assignIpv6Result = serverDriver.assignIpv6(finalVendor.getUuid(),
												interfaces.get(0).getNetworkInterfaceUuid(), ipV6Address,
												interfaces.get(0).getRegionId());
										if (assignIpv6Result.isSuccess()) {
											break;
										}
										num++;
									}
									if (assignIpv6Result.isFailed()) {
										logger.error("虚机IpV6设置失败 {} ", assignIpv6Result.getMessage());
										resourceEventPublisher.send(new OperateResult(assignIpv6Result.isSuccess(),
												"虚机IpV6设置失败", finalVendor.getType().toLowerCase() + ".vm",
												MapTools.simpleMap(Common.VENDORID, vendorId), operateCategory,
												context));
									} else {
										// 回填IPv6
										privateIps.add(ipV6Address);
										cloudServer.setPrivateIps(privateIps.toJSONString());
										cloudServerRepository.update(cloudServer);
									}
								}
							}
						} catch (Exception e) {
							logger.error("虚机IpV6设置失败 {} ", e.getMessage());
							resourceEventPublisher.send(
									new OperateResult(false, "虚机IpV6设置失败", finalVendor.getType().toLowerCase() + ".vm",
											MapTools.simpleMap(Common.VENDORID, vendorId), operateCategory, context));
						}
						try {
							if (params.getHasEip()) {
								Long eipId = params.getEipId();
								ElasticIp elasticIp = null;
								if (eipId == null) {
									ElasticIp elasticIpInfo = new ElasticIp();
									elasticIpInfo.setName("EIP_" + UUID.randomUUID());
									elasticIpInfo.setVendorId(vendorId);
									elasticIpInfo.setRegionId(params.getRegionId());
									BocloudResult allocateResult = elasticIpService.allocate(elasticIpInfo, context);
									if (allocateResult.isFailed()) {
										logger.error("EIP分配失败 {} ", allocateResult.getMessage());
										resourceEventPublisher.send(new OperateResult(allocateResult.isSuccess(),
												"EIP分配失败", finalVendor.getType().toLowerCase() + ".vm",
												MapTools.simpleMap(Common.VENDORID, vendorId), operateCategory,
												context));
									} else {
										elasticIp = (ElasticIp) allocateResult.getData();
									}
								} else {
									elasticIp = elasticIpRepository.query(eipId);
								}
								if (null == elasticIp) {
									logger.error("EIP数据不存在");
									resourceEventPublisher.send(new OperateResult(false, "EIP数据不存在",
											finalVendor.getType().toLowerCase() + ".vm",
											MapTools.simpleMap(Common.VENDORID, vendorId), operateCategory, context));
								} else {
									ElasticIpGenericParam elasticIpGenericParam = new ElasticIpGenericParam();
									elasticIpGenericParam.setId(elasticIp.getId());
									elasticIpGenericParam.setInstanceId(cloudServer.getInstanceId());
									elasticIpGenericParam.setAllowReassociation(true);
									BocloudResult associateResult = elasticIpService.associate(elasticIpGenericParam,
											context);
									if (associateResult.isFailed()) {
										logger.error("虚机EIP关联失败 {} ", associateResult.getMessage());
										resourceEventPublisher.send(new OperateResult(associateResult.isSuccess(),
												"虚机关联EIP失败", finalVendor.getType().toLowerCase() + ".vm",
												MapTools.simpleMap(Common.VENDORID, vendorId), operateCategory,
												context));
									}

								}
							}
						} catch (Exception e) {
							logger.error("虚机关联EIP失败 {} ", e.getMessage());
							resourceEventPublisher.send(
									new OperateResult(false, "虚机关联EIP失败", finalVendor.getType().toLowerCase() + ".vm",
											MapTools.simpleMap(Common.VENDORID, vendorId), operateCategory, context));
						}
					}

				});
			}
			// 发送给云平台统计队列对云平台重新统计
			JSONObject jsonObject = new JSONObject();
			jsonObject.put(Common.VENDORID, vendorId);
			amqpTemplate.convertAndSend("vendor.statistics.queue", jsonObject);
			logger.info("Batch create virtual machine task submission is completed, waiting for results...");
		}).start();
		return new BocloudResult(true, "创建任务已经下发，正在执行……");
	}

	@Override
	public BocloudResult clone(VmGenericParam vmGenericParam, RequestContext context) {
		try {
			Integer count = vmGenericParam.getCount();
			CloudServer bean = new CloudServer();
			BeanUtils.copyProperties(vmGenericParam, bean);
			String name = bean.getName();
			Long hostId = bean.getHostId();
			CloudServer server = cloudServerRepository.query(bean.getId());
			Optional.ofNullable(server).orElseThrow(() -> new Exception("克隆的模板虚拟机不存在"));
			Long vendorId = server.getVendorId();
			CloudVendor vendor = cloudVendorRepository.query(vendorId);
			Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
			if (cloudServerRepository.exists(name, vendor.getId())) {
				return new BocloudResult(false, "虚拟机名称已存在!");
			}
			Server host = serverRepository.query(hostId);
			Optional.ofNullable(host).orElseThrow(() -> new Exception("目标宿主机不存在"));
			List<NetcardOperation> operations = vmGenericParam.getOperations();
			if (ListTool.isEmpty(operations)) {
				// 查询模板的网卡
				List<NetworkCard> cards = networkCardRepository.listByHost(server.getId(), "VM");
				if (ListTool.isEmpty(cards)) {
					return new BocloudResult(false, "虚拟机模板上无任何网卡");
				}
				operations = Lists.newArrayList();
				for (NetworkCard card : cards) {
					NetcardOperation operation = new NetcardOperation();
					operation.setName(card.getName());
					operation.setOperation("EDIT");
					operation.setLabel(card.getLabel());
					operation.setPortType(card.getPortType());
					operation.setMac(card.getMac());
					operations.add(operation);
				}
			}
			List<ProcessResult> processResults = Lists.newArrayList();
			// VCenter分配的虚拟机IP
			List<Ip> ips = Lists.newArrayList();
			for (int i = 0; i < count; i++) {
				String serverName = "";
				if (count == 1) {
					serverName = name;
				} else {
					serverName = name + "_" + (i + 1);
				}
				// 分配IP
				BocloudResult bocloudResult = serverOperationHelper.assignIp(vendor, operations);
				List<Ip> ipList = JSONArray.parseArray(JSONObject.toJSONString(bocloudResult.getData()), Ip.class);
				if (bocloudResult.isFailed()) {
					return new BocloudResult(false, bocloudResult.getMessage());
				}
				ips.addAll(ipList);
				JSONObject object = JSONObject.parseObject(JSONObject.toJSONString(vmGenericParam));
				object.put("name", serverName);
				object.put("operations", JSONObject.toJSON(operations));
				object.put("templateId", server.getId());
				object.put("cpu", server.getCpu());
				object.put("memory", server.getMemory());
				Volume systemDisk = volumeRepository.getSystemDisk(server.getId());
				if (null != systemDisk) {
					object.put("disk", systemDisk.getSize());
				} else {
					object.put("disk", server.getDisk());
				}
				object.put("addShterm", server.getIsAddShterm());
				ServerBuilder builder = new VMServerBuilder(cloudServerRepository, serverRepository,
						dataStoreRepository, networkRepository, networkCardRepository, portGroupRepository,
						switcherRepository, storeHostRepository, networkHostRepository, ipRepository,
						resourceRepository, resourceEventRepository, volumeRepository, serverLabelRepository,
						serverDriver, context, vendor, resourceEventPublisher, ipPoolRepository, smsTenantService,
						lockFactory, smsProjectService, lvmService, amqpTemplate);
				BocloudResult<ServerModel> result = builder.prepare(object);
				if (result.isFailed()) {
					// 回收IP
					serverOperationHelper.recycleIp(ips, null, vendor.getId());
					return new BocloudResult(false, "虚拟机克隆失败：" + result.getMessage());
				}
				ServerModel model = result.getData();
				processResults.add(new ProcessResult(model, builder));
			}
			final Integer finalCount = count;
			new Thread(() -> {
				String operate = vendor.getType().toLowerCase() + ".vm";
				logger.info("Batch clone virtual machine 【" + name + "】 start...");
				// 创建成功的虚拟机
				List<BocloudResult> succList = Lists.newArrayList();
				// 创建失败的虚拟机
				List<BocloudResult> failList = Lists.newArrayList();
				List<Future<BocloudResult<CloudServer>>> futures = new ArrayList<>();
				try {
					// 保存虚拟机的一些基本信息
					for (ProcessResult processResult : processResults) {
						ServerModel model = processResult.getServerModel();
						CloudServer cloudServer = JSONObject.parseObject(JSONObject.toJSONString(model),
								CloudServer.class);
						cloudServer.setStatus(BocloudStatus.Server.BUILDING.name());
						cloudServer.setIsTemplate(false);
						cloudServer.setRegion(server.getRegion());
						cloudServer.setAccount(server.getAccount());
						cloudServer.setPswd(server.receivePswd());
						cloudServer.preSave(context.getTarget(), context.getTarget(), vendor.getId(), hostId,
								model.getVdcId(), null, server.getTenantId(), server.getProjectId());
						cloudServer.setResourceId(IDFactory.instance().uuid());
						cloudServer.setVendorType(vendor.getType());
						cloudServer.setRecycle(false);
						cloudServerRepository.save(cloudServer);
						processResult.setCloudServer(cloudServer);
					}
					resourceEventPublisher.send(new OperateResult(true, "虚拟机克隆中，请耐心等待", operate,
							MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
					// 执行创建虚拟机的操作
					for (ProcessResult processResult : processResults) {
						futures.add(taskExecutor.submit(
								() -> processResult.getServerBuilder().builder(processResult.getCloudServer())));
					}
					// 获取线程池返回结果
					for (int i = 0; i < futures.size(); i++) {
						BocloudResult<CloudServer> result = futures.get(i).get(1, TimeUnit.HOURS);
						CloudServer cloudServer = result.getData();
						ResourceEvent event = null;
						if (result.isSuccess()) {
							BocloudResult bocloudResult = new BocloudResult(true,
									"【" + cloudServer.getName() + "】克隆成功【" + result.getMessage() + "】");
							succList.add(bocloudResult);
							event = new ResourceEvent(bean.getId(), "虚拟机克隆", "成功", context.getTarget(), new Date(),
									"VM", vendor.getId(), context.getCatalog());
						} else {
							BocloudResult bocloudResult = new BocloudResult(true,
									"【" + cloudServer.getName() + "】克隆失败【" + result.getMessage() + "】");
							failList.add(bocloudResult);
							event = new ResourceEvent(bean.getId(), "虚拟机克隆", "失败", context.getTarget(), new Date(),
									"VM", vendor.getId(), context.getCatalog());
						}
						resourceEventRepository.save(event);
					}
					// 创建成功的数量
					int success = succList.size();
					// 创建失败的数量
					int fail = failList.size();
					// 发送站内信
					String content = null;
					if (fail == finalCount) {
						content = "【" + name + "】虚拟机克隆失败，详情如下：\n";
						for (BocloudResult bocloudResult : failList) {
							content += bocloudResult.getMessage() + "\n";
						}
					} else {
						content = "【" + name + "】虚拟机克隆成功【" + success + "】个,失败【" + fail + "】个，详情如下：\n";
						for (BocloudResult bocloudResult : succList) {
							content += bocloudResult.getMessage() + "\n";
						}
						for (BocloudResult bocloudResult : failList) {
							content += bocloudResult.getMessage() + "\n";
						}
					}
					resourceEventPublisher.send(new OperateResult(fail == 0, content, operate,
							MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
					logger.info("Batch clone virtual machine 【" + name + "】 end...");
				} catch (Exception e) {
					logger.error("Get Message Exception:", e);
					// 回收IP
					serverOperationHelper.recycleIp(ips, null, vendor.getId());
					resourceEventPublisher.send(new OperateResult(false, "虚拟机克隆失败", operate,
							MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
				}
			}).start();
			return new BocloudResult(true, "虚拟机克隆任务已经下发，正在执行……");
		} catch (Exception e) {
			logger.error("Clone server error:", e);
			return new BocloudResult(false, "虚拟机克隆失败!");
		}
	}

	public BocloudResult cloneAsTemplate(VmGenericParam vmGenericParam, RequestContext context) {
		try {
			JSONObject object = JSONObject.parseObject(JSON.toJSONString(vmGenericParam));
			object = Optional.ofNullable(object).orElseThrow(() -> new Exception("参数格式不正确"));
			CloudServer bean = JSONObject.parseObject(object.toJSONString(), CloudServer.class);
			String name = bean.getName();
			Long hostId = bean.getHostId();
			CloudServer server = cloudServerRepository.query(bean.getId());
			server = Optional.ofNullable(server).orElseThrow(() -> new Exception("克隆的模板虚拟机不存在"));
			object.put("template", server.getName());
			object.put("templateId", server.getId());
			Long vendorId = server.getVendorId();
			CloudVendor vendor = cloudVendorRepository.query(vendorId);
			vendor = Optional.ofNullable(vendor).orElseThrow(() -> new Exception("获取云供应商失败"));
			if (cloudServerRepository.exists(name, vendor.getId())) {
				return new BocloudResult(false, "虚拟机名称已存在!");
			}
			Server host = serverRepository.query(hostId);
			host = Optional.ofNullable(host).orElseThrow(() -> new Exception("目标宿主机不存在"));
			ServerBuilder builder = new VMServerBuilder(cloudServerRepository, serverRepository, dataStoreRepository,
					networkRepository, networkCardRepository, portGroupRepository, switcherRepository,
					storeHostRepository, networkHostRepository, ipRepository, resourceRepository,
					resourceEventRepository, volumeRepository, serverLabelRepository, serverDriver, context, vendor,
					resourceEventPublisher, ipPoolRepository, smsTenantService, lockFactory, imageRepository,
					smsProjectService, lvmService, amqpTemplate);
			BocloudResult<ServerModel> result = builder.prepare(object);
			if (result.isFailed()) {
				return new BocloudResult(false, "虚拟机克隆模板失败：" + result.getMessage());
			}
			final CloudVendor finalVendor = vendor;
			new Thread(() -> {
				String operate = finalVendor.getType().toLowerCase() + ".vm";
				logger.info("clone virtual machine as template 【" + name + "】 start...");
				try {
					ServerModel model = result.getData();
					CloudServer cloudServer = JSONObject.parseObject(JSONObject.toJSONString(model), CloudServer.class);
					cloudServer.setStatus(BocloudStatus.Server.BUILDING.name());
					cloudServer.setIsTemplate(true);
					cloudServer.preSave(context.getTarget(), context.getTarget(), finalVendor.getId(), hostId,
							model.getVdcId(), null, context.getTenant(), context.getProject());
					cloudServer.setResourceId(IDFactory.instance().uuid());
					cloudServer.setVendorType(finalVendor.getType());
					cloudServer.setRecycle(false);
					cloudServerRepository.save(cloudServer);
					BocloudResult<CloudServer> buildResult = builder.builderAsTemplate(cloudServer);
					ResourceEvent event = new ResourceEvent(bean.getId(), "虚拟机克隆",
							buildResult.isSuccess() ? "成功" : "失败", context.getTarget(), new Date(), "VM",
							finalVendor.getId(), context.getCatalog());
					resourceEventRepository.save(event);
					resourceEventPublisher.send(new OperateResult(buildResult.isSuccess(), buildResult.getMessage(),
							operate, MapTools.simpleMap(Common.VENDORID, finalVendor.getId()), operateCategory,
							context));
					logger.info("clone virtual machine as template 【" + name + "】 end...");
				} catch (Exception e) {
					logger.error("Get Message Exception:", e);
					resourceEventPublisher.send(new OperateResult(false, "虚拟机克隆模板失败", operate,
							MapTools.simpleMap(Common.VENDORID, finalVendor.getId()), operateCategory, context));
				}
			}).start();
			return new BocloudResult(true, "虚拟机克隆模板任务已经下发，正在执行……");
		} catch (Exception e) {
			logger.error("Clone server error：{}", e.getMessage());
			return new BocloudResult(false, "虚拟机克隆模板失败：" + e.getMessage());
		}
	}

	@Override
	public BocloudResult migrate(VmGenericParam vmGenericParam, RequestContext context) {
		try {
			JSONObject object = JSONTools.isJSONObj(JSON.toJSONString(vmGenericParam));
			Long id = object.getLong(Common.ID);
			Long hostId = object.getLong("hostId");
			Long storeId = object.getLong("storeId");
			String diskLocators = object.getString("diskLocators");
			CloudServer server = cloudServerRepository.query(id);
			Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
			CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
			Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云供应商不存在"));
			ServerModel model = new ServerModel();
			model.setName(server.getName());
			Server host = null;
			if (!StringUtils.isEmpty(diskLocators)) {
				List<JSONObject> locators = JSONArray.parseArray(diskLocators, JSONObject.class);
				List<JSONObject> newLocators = Lists.newArrayList();
				for (JSONObject locator : locators) {
					Long dsId = locator.getLong("storeId");
					Long diskId = locator.getLong("diskId");
					DataStore store = dataStoreRepository.query(dsId);
					store = Optional.ofNullable(store).orElseThrow(() -> new Exception("要迁移的数据存储不存在"));
					Volume disk = volumeRepository.query(diskId);
					disk = Optional.ofNullable(disk).orElseThrow(() -> new Exception("要迁移的磁盘不存在"));
					locator.put("dsName", store.getName());
					locator.put("diskName", disk.getName());
					newLocators.add(locator);
				}
				model.setDiskLocators(newLocators);
			} else if (null != storeId && 0L != storeId) {
				// 更改数据存储
				DataStore store = dataStoreRepository.query(storeId);
				store = Optional.ofNullable(store).orElseThrow(() -> new Exception("数据存储不存在"));
				model.setStoreName(store.getName());
				// 更改宿主机
				if (null != hostId && 0L != hostId) {
					// if
					// (!BocloudStatus.Server.STOPPED.name().equals(server.getStatus()))
					// {
					// return new BocloudResult(false,
					// "要更改虚拟机的主机和数据存储，必须关闭虚拟机电源！");
					// }
					host = serverRepository.query(hostId);
					host = Optional.ofNullable(host).orElseThrow(() -> new Exception("宿主机不存在"));
					model.setHostName(host.getName());
				} else {
					host = serverRepository.query(server.getHostId());
					host = Optional.ofNullable(host).orElseThrow(() -> new Exception("数据存储关联的宿主机不存在"));
				}
				model.setClusterName(host.getClusterName());
				model.setVdcName(host.getVdcName());
			} else if (null != hostId && 0L != hostId) {
				host = serverRepository.query(hostId);
				host = Optional.ofNullable(host).orElseThrow(() -> new Exception("宿主机不存在"));
				model.setHostName(host.getName());
				model.setClusterName(host.getClusterName());
				model.setVdcName(host.getVdcName());
			} else {
				return new BocloudResult(false, "参数格式错误，未选择任何宿主机或数据存储");
			}
			model.setStatus(server.getStatus());
			model.setInstanceId(server.getInstanceId());
			final Server finalHost = host;
			new Thread(() -> {
				String operate = vendor.getType().toLowerCase() + ".vm";
				BocloudResult result = serverDriver.migrate(vendor.getUuid(), null, model);
				try {
					if (result.isSuccess()) {
						server.setIsTemplate(false);
						if (null != storeId && 0L != storeId) {
							List<StoreHost> vmStores = storeHostRepository.list(server.getId(), "VM");
							if (!ListTool.isEmpty(vmStores)) {
								List<StoreHost> updateVmStores = Lists.newArrayList();
								for (StoreHost vmStore : vmStores) {
									StoreHost updateVmStore = new StoreHost(storeId, server.getId(),
											server.getVendorId(), "VM");
									updateVmStore.setId(vmStore.getId());
									updateVmStores.add(updateVmStore);
								}
								storeHostRepository.batchSave(updateVmStores);
							}
						}
						if (null != hostId && 0L != hostId) {
							server.setHostId(hostId);
						}
						cloudServerRepository.update(server);
					}
					ResourceEvent event = new ResourceEvent(id, "虚拟机迁移", result.isSuccess() ? "成功" : "失败",
							context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
					resourceEventRepository.save(event);
				} catch (Exception e) {
					logger.error("migrate server error:", e);
				}
				resourceEventPublisher.send(
						new OperateResult(result.isSuccess(), "虚拟机迁移" + (result.isSuccess() ? "成功" : "失败"), operate,
								MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
			}).start();
			return new BocloudResult(true, "迁移任务已经下发，正在执行……");
		} catch (Exception e) {
			logger.error("create server error:", e);
			return new BocloudResult(false, "迁移失败:" + e.getMessage());
		}
	}

	@Override
	public BocloudResult osMigrate(VmGenericParam vmGenericParam, RequestContext context) {
		JSONObject object = JSONTools.isJSONObj(JSON.toJSONString(vmGenericParam));
		Long serverId = object.getLong("serverId");
		Boolean live = null == object.getBoolean("live") ? true : object.getBoolean("live");
		Long hostId = object.getLong("hostId");
		OSMigrateModel migrate = new OSMigrateModel();
		migrate.setLive(live);
		try {
			CloudServer server = cloudServerRepository.query(serverId);
			Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
			CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
			Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
			Server host = null;
			if (null != hostId) {
				host = serverRepository.query(hostId);
				Optional.ofNullable(vendor).orElseThrow(() -> new Exception("新主机不存在"));
				/**
				 * 电科云 2019年12月5日13:55:25 电科云环境 虚拟迁移
				 */
				migrate.setHost(host.getHostname());
			}
			List<Server> servers = serverRepository.listByVendor(vendor.getId());
			if (servers.size() == 1) {
				return new BocloudResult(false, "当前云平台只有一台宿主机，迁移失败");
			}
			migrate.setInstanceId(server.getInstanceId());
			Server cloneHost = host;
			new Thread(() -> {
				String operate = vendor.getType().toLowerCase() + ".vm";
				OperateResult message = new OperateResult(false, "虚拟机迁移失败！", operate,
						MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context);
				try {
					BocloudResult result = serverDriver.migrate(vendor.getUuid(), null, migrate);
					if (result.isSuccess()) {
						CloudProvider provider = CloudProvider.valueOf(vendor.getType());
						switch (provider) {
						case MANAGEONE:
							ServerModel serverModel = serverOperationHelper.parseObject(result.getData(),
									ServerModel.class);
							if (null != cloneHost) {
								server.setHostId(cloneHost.getId());
							} else {
								Server byHostName = serverRepository.getByHostName(serverModel.getHostName(),
										vendor.getId());
								if (null != byHostName) {
									server.setHostId(byHostName.getId());
								}
							}
							cloudServerRepository.update(server);
							break;
						default:
							// 原迁移代码
							VMBean bean = serverOperationHelper.parseObject(result.getData(), VMBean.class);
							bean.setPrivateIps(server.getPrivateIps());
							bean.setOsCategory(server.getOsCategory());
							bean.setIsTemplate(server.getIsTemplate());
							BeanUtils.copyProperties(bean, server);
							String guid = null;
							if (null != hostId) {
								guid = cloneHost.getGuid();
								server.setHostId(hostId);
								cloudServerRepository.update(server);
							} else {
								// 离线迁移
								if (null != bean.getHostName()) {
									Server host1 = serverRepository.getByName(bean.getHostName(), vendor.getId());
									if (null != host1) {
										server.setHostId(host1.getId());
										guid = host1.getGuid();
									}
								}
								server.setStatus(BocloudStatus.Server.STOPPED.name());
								cloudServerRepository.update(server);
							}
							break;
						}
						message.setSuccess(true);
						message.setMessage("虚拟机迁移成功");
					} else {
						message.setMessage("虚拟机迁移失败!【" + result.getMessage() + "】");
					}
					ResourceEvent event = new ResourceEvent(serverId, "虚拟机迁移", result.isSuccess() ? "成功" : "失败",
							context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
					resourceEventRepository.save(event);
				} catch (Exception e) {
					logger.error("osmigrate server error:", e);
				}
				resourceEventPublisher.send(message);
			}).start();
			return new BocloudResult(true, "迁移任务已经下发，正在执行……");
		} catch (Exception e) {
			logger.error("get cloudvendor and reg error:", e);
			return new BocloudResult(false, "虚拟机迁移失败:" + e.getMessage());
		}
	}
	
	public BocloudResult snapshotQuotasCallBack(RequestContext context, Action action) {
		try {
			if(null == context.getCatalog()) {
				return new BocloudResult<>(true, "快照配额分配成功"); 
			}
			if (context.getCatalog().equals(Catalog.User) || context.getCatalog().equals(Catalog.Tenant)) {
				List<ResourceQuota> quotas = new ArrayList<>();
				String snapshotServiceCode = "meta.snapshot";
				quotas.add(new ResourceQuota(snapshotServiceCode, 1L));
				BocloudResult updateQuotas = cosInternalService.updateQuotas(quotas, action, context.getTenant());
				if (updateQuotas.isFailed()) {
					return new BocloudResult<>(false, "快照创建失败：" + updateQuotas.getMessage());
				}
			}
			return new BocloudResult<>(true, "快照配额分配成功");
		} catch (Exception e) {
			logger.error("快照创建失败：" + e.getMessage());
			return new BocloudResult<>(false, "快照创建失败：" + e.getMessage());
		}
	}

	@Override
	public BocloudResult snapshot(VmSnapshotParam params, RequestContext context) {
		Long serverId = params.getServerId();
		String name = params.getName();
		String remark = params.getRemark();
		String path = CloudServer.class.getSimpleName() + "_" + serverId;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			CloudServer server = cloudServerRepository.query(serverId);
			Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
			CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
			Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
			// 定时快照cron表达式
			String cron = params.getCron();
			if (!StringUtils.isEmpty(cron)) {
				snapshotTaskService.removeByVmId(serverId);
				SnapshotTask snapshotTask = new SnapshotTask(name, remark, serverId, null, server.getVendorId(), cron,
						IDFactory.instance().uuid());
				snapshotTaskRepository.save(snapshotTask);
				BocloudResult snapTaskResult = snapshotTaskService.create(snapshotTask.getTaskId(), context);
				if (snapTaskResult.isFailed()) {
					return snapTaskResult;
				}
				return new BocloudResult(true, "定时快照任务启动成功");
			}
			// 如果是租户快照 咋进行配额回滚操作
			BocloudResult snapshotQuotasCallBack = this.snapshotQuotasCallBack(context, Action.Order);
			if(snapshotQuotasCallBack.isFailed()) {
				return snapshotQuotasCallBack;
			}
			Long userId = context.getTarget();
			CloudProvider type = CloudProvider.valueOf(vendor.getType());
			switch (type) {
			case OPENSTACK:
				break;
			case VMWARE:
				Server host = serverRepository.query(server.getHostId());
				Optional.ofNullable(host).orElseThrow(() -> new Exception("宿主机不存在"));
				if (null != host.getMaintained() && host.getMaintained()) {
					snapshotQuotasCallBack(context, Action.Callback);
					return new BocloudResult(false, "该虚拟机所在宿主机处于维护模式下，无法执行创建快照任务");
				}
				break;
			case POWERVC:
				if (server.getStatus().equals(BocloudStatus.Server.RUNNING.name())) {
					return new BocloudResult(false, "开机状态的power虚拟机，不允许捕获快照!");
				}
				break;
			default:
				break;
			}
			SnapshotModel model = new SnapshotModel(name, remark, null, server.getInstanceId());
			new Thread(() -> {
				String operate = vendor.getType().toLowerCase() + ".vm.snapshot";
				if (!(vendor.getType().toLowerCase() + ".vm.snapshot").equals(params.getOperate())) {
					operate = vendor.getType().toLowerCase() + ".snapshot";
				}
				OperateResult message = new OperateResult(false, "创建快照失败", operate,
						MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context);
				try {
					BocloudResult result = serverDriver.snapshot(model, vendor.getUuid(), null);
					if (result.isSuccess()) {
						List<Image> images = Lists.newArrayList();
						List<Snapshot> snaps = Lists.newArrayList();
						String content = JSONObject.toJSONString(result.getData());
						switch (type) {
						case OPENSTACK:
							message.setOperate(operate);
							JSONObject jsonObject = JSONObject.parseObject(content);
							Object imgObj = jsonObject.get("image");
							if (null != imgObj) {
								ImageModel imgModel = JSONObject.parseObject(JSONObject.toJSONString(imgObj),
										ImageModel.class);
								Image image = new Image();
								BeanUtils.copyProperties(imgModel, image);
								image.setRemark(remark);
								image.setName(name);
								image.setVendorType(vendor.getType());
								image.preSave(userId, userId, vendor.getId(), server.getTenantId(),
										server.getProjectId());
								image.setCatalog("VM");
								imageRepository.save(image);
								images.add(image);
							}
							Object snapshotsObject = jsonObject.get("snapshots");
							if (null != snapshotsObject) {
								List<Snapshot> snapshots = snapshotRepository.listByVid(vendor.getId());
								Map<String, Snapshot> snapshotMap = Maps.newHashMap();
								for (Snapshot snapshot : snapshots) {
									snapshotMap.put(snapshot.getSnapshotUuid(), snapshot);
								}
								List<SnapshotModel> snapshotModels = JSONArray
										.parseArray(JSONObject.toJSONString(snapshotsObject), SnapshotModel.class);
								for (SnapshotModel snapshotModel : snapshotModels) {
									Volume volume = volumeRepository.getByVolumeUuid(snapshotModel.getVolumeUuid());
									if (snapshotMap.containsKey(snapshotModel.getSnapshotUuid())) {
										Snapshot oldSnapshot = snapshotMap.get(snapshotModel.getSnapshotUuid());
										BeanUtils.copyProperties(snapshotModel, oldSnapshot);
										oldSnapshot.setRemark(remark);
										oldSnapshot.setVmId(serverId);
										if (null != volume) {
											oldSnapshot.setVolumeId(volume.getId());
										}
										oldSnapshot.setTenantUuid(server.getTenantUuid());
										snapshotRepository.update(oldSnapshot);
									} else {
										Snapshot snapshot = new Snapshot();
										BeanUtils.copyProperties(snapshotModel, snapshot);
										snapshot.setRemark(remark);
										snapshot.preSave(userId, userId, vendor.getId(), serverId, server.getTenantId(),
												server.getProjectId());
										if (null != volume) {
											snapshot.setVolumeId(volume.getId());
										}
										snapshot.setTenantUuid(server.getTenantUuid());
										snapshotRepository.save(snapshot);
										snaps.add(snapshot);
									}
								}
							}
							break;
						case VMWARE:
							Snapshot snapshot = JSONObject.parseObject(content, Snapshot.class);
							snapshot.preSave(userId, userId, server.getVendorId(), serverId, server.getTenantId(),
									server.getProjectId());
							if (null == snapshot.getSize()) {
								snapshot.setSize(0);
							}
							snapshot.setCatalog(context.getCatalog());
							snapshot.setSnapshotType("VM");
							snapshot.setParentId(getParentSnapshot(serverId));
							snapshotRepository.save(snapshot);
							snaps.add(snapshot);
							break;
						case MANAGEONE:
							List<SnapshotModel> snapshotModels = JSONObject.parseArray(content, SnapshotModel.class);
							if (!ListTool.isEmpty(snapshotModels)) {
								for (SnapshotModel moModel : snapshotModels) {
									Snapshot manageOneSnapshot = new Snapshot();
									BeanUtils.copyProperties(moModel, manageOneSnapshot);
									if (!StringUtils.isEmpty(moModel.getVolumeUuid())) {
										Volume volume = volumeRepository.getByVolumeUuid(moModel.getVolumeUuid(),
												vendor.getId());
										if (null != volume) {
											manageOneSnapshot.setVolumeId(volume.getId());
										}
									}
									manageOneSnapshot.preSave(userId, userId, vendor.getId(), null, context.getTarget(),
											context.getProject());
									if (!StringUtils.isEmpty(model.getInstanceId())) {
										CloudServer cloudServer = cloudServerRepository
												.getByInstanceId(model.getInstanceId(), vendor.getId());
										if (null != cloudServer) {
											manageOneSnapshot.setVmId(cloudServer.getId());
										}
									}
									manageOneSnapshot.setRemark(remark);
									snapshotRepository.save(manageOneSnapshot);
								}
							}
							break;
						case H3C:
							Snapshot h3cSnapshot = new Snapshot();
							h3cSnapshot.preSave(userId, userId, server.getVendorId(), serverId, server.getTenantId());
							h3cSnapshot.setName(name);
							h3cSnapshot.setRemark(remark);
							h3cSnapshot.setCreateTime(new Date());
							h3cSnapshot.setStatus("AVAILABLE");
							h3cSnapshot.setSnapshotType("VM");
							h3cSnapshot.setSnapshotVal(name);
							snapshotRepository.save(h3cSnapshot);
							break;
						default:
							break;
						}
						if (null != server.getTenantId() && 0L != server.getTenantId()) {
							// 保存relation
							for (Snapshot snapshot : snaps) {
								snapshot.setExpiredTime(server.getExpiredTime());
							}
						}
					} else {
						snapshotQuotasCallBack(context, Action.Callback);
					}
					ResourceEvent event = new ResourceEvent(serverId, "虚拟机创建快照", result.isSuccess() ? "成功" : "失败",
							userId, new Date(), "SNAPSHOT", vendor.getId(), context.getCatalog());
					resourceEventRepository.save(event);
					message.setSuccess(result.isSuccess());
					message.setMessage(result.getMessage());
				} catch (Exception e) {
					snapshotQuotasCallBack(context, Action.Callback);
					logger.error("Get Message Exception:", e);
				}
				resourceEventPublisher.send(message);
			}).start();
			return new BocloudResult(true, "创建快照任务已经下发，正在执行……");
		} catch (Exception e) {
			logger.error("create server error:", e);
			return new BocloudResult(false, "创建失败:" + e.getMessage());
		}
	}

	private Long getParentSnapshot(Long serverId) throws Exception {
		String path = CloudServer.class.getSimpleName() + "_task_snapshot_" + serverId;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			// 查询没有子快照的快照，即为当前快照位置
			List<Snapshot> snapshots = snapshotRepository.listByVMid(serverId);
			if (ListTool.isEmpty(snapshots)) {
				return 0L;
			}
			for (Snapshot snapshot : snapshots) {
				List<Snapshot> children = snapshotRepository.list(snapshot.getId(), null, serverId);
				if (ListTool.isEmpty(children)) {
					return snapshot.getId();
				}
			}
		} catch (Exception e) {
			logger.error("更新子快照异常：" + e.getMessage());
		}
		return 0L;
	}

	@Override
	public BocloudResult modify(CloudServerBean bean, RequestContext context, String queue) {
		Long serverId = bean.getId();
		String path = CloudServer.class.getSimpleName() + "_" + serverId;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			CloudServer vm = this.cloudServerRepository.query(serverId);
			String oldName = vm.getName();
			Assert.notNull(vm, "虚拟机不存在");
			CloudVendor vendor = cloudVendorRepository.query(vm.getVendorId());
			Assert.notNull(vendor, "云平台不存在");
			// 名称不能重复, Powervc的名称可以重复
			if (!vm.getName().equalsIgnoreCase(bean.getName())
					&& !CloudProvider.POWERVC.name().equals(vendor.getType())) {
				boolean flag = cloudServerRepository.exists(bean.getName(), vendor.getId());
				if (flag) {
					return new BocloudResult(false, "虚拟机名称不能重复");
				}
			}
			CloudProvider type = CloudProvider.valueOf(vendor.getType());
			ServerModel model = JSONObject.parseObject(JSONObject.toJSONString(bean), ServerModel.class);
			model.setInstanceId(vm.getInstanceId());
			switch (type) {
			case VMWARE:
				BeanUtils.copyProperties(bean, vm);
				Server host = serverRepository.query(vm.getHostId());
				model.setHostName(host.getName());
				model.setVdcName(host.getVdcName());
				if (null == vm.getIsTemplate() || !vm.getIsTemplate()) {
					model.setMemory(bean.getMemory());
					model.setCpu(bean.getCpu());
				}
				break;
			case OPENSTACK:
			case MANAGEONE:
			case FUSIONCLOUD:
			case TCE:
			case PQCLOUD:
			case AWS:
			case AZURE:
				String jdName = bean.getName();
				if (!StringUtils.isEmpty(jdName)) {
					model.setName(jdName);
				}
				String jdRemark = bean.getRemark();
				if (!StringUtils.isEmpty(jdRemark)) {
					model.setRemark(jdRemark);
				}
				break;
			case POWERVC:
				model = new ServerModel();
				model.setInstanceId(vm.getInstanceId());
				model.setName(bean.getName());
				model.setRemark(bean.getRemark());
				break;
			default:
				break;
			}
			ServerModel serverModel = model;
			// 启动一个线程
			new Thread(() -> {
				BocloudResult result = null;
				if (CloudProvider.MANAGEONE.name().equals(vendor.getType()) && null != context.getTenant()
						&& 0L != context.getTenant()) {
					ManageOneAccount account = accountService.queryAccount(vendor.getId(), context.getTenant());
					Assert.notNull(account, "认证失败！");
					result = serverDriver.modify(vendor.getUuid(), account.getUsername(), account.getPassword(),
							account.getProjectId(), account.getDomainName(), serverModel);
				} else {
					result = serverDriver.modify(vendor.getUuid(), vm.getRegionId(), serverModel);
				}
				if (!StringUtils.isEmpty(queue)) {
					BocloudResult bocloudResult = new BocloudResult(result.isSuccess(), result.getMessage());
					if (result.isSuccess()) {
						bocloudResult.setData(result.getData());
					}
					amqpTemplate.convertAndSend(queue, JSONObject.toJSON(bocloudResult));
				}
				ResourceEvent event = null;
				String operate = vendor.getType().toLowerCase() + ".vm";
				try {
					if (result.isSuccess()) {
						String content = JSONObject.toJSONString(result.getData());
						CloudServer server = JSONObject.parseObject(content, CloudServer.class);
						switch (type) {
						case VMWARE:
							// 同步该虚拟机和网络的关系
							Server host = serverRepository.query(vm.getHostId());
							Map<String, Network> networkMap = Maps.newHashMap();
							Map<String, String> groupMap = Maps.newHashMap();
							List<Network> oldNetworks = networkRepository.listByVdc(host.getVdcId());
							oldNetworks.forEach(n -> networkMap.put(n.getNetworkVal(), n));
							List<Switcher> switchers = switcherRepository.listByVdc(host.getVdcId(), "DVSWITCH");
							for (Switcher switcher : switchers) {
								List<PortGroup> groups = portGroupRepository.listBySwitcher(switcher.getId());
								for (PortGroup group : groups) {
									groupMap.put(group.getGroupVal(), switcher.getSwitcherVal());
								}
							}
							SyncVmwareUtils utils = new SyncVmwareUtils(cloudServerRepository, dataStoreRepository,
									serverRepository, snapshotRepository, networkRepository, null, storeHostRepository,
									networkCardRepository, portGroupRepository, networkHostRepository, null, null,
									ipRepository, imageRepository, volumeRepository);
							utils.mergeNetworkHost(vendor.getId(), serverId, "VM", server.getNetworks(), networkMap,
									groupMap);
							// 同步该虚拟机下的虚拟网卡
							List<NetworkCard> oldCards = networkCardRepository.listByHost(serverId, "VM");
							utils.syncNetworkCard(oldCards, server.getNetcards(), vendor.getId(), serverId,
									context.getTarget(), "VM", Maps.newHashMap());
							List<DataStore> stores = dataStoreRepository.listByVendor(vendor.getId());
							Map<String, DataStore> storeMap = new HashMap<>(8);
							stores.forEach(s -> storeMap.put(s.getStoreVal(), s));
							// 同步该虚拟机下的硬盘设备
							List<Volume> oldDisks = volumeRepository.listByServerId(serverId);
							utils.syncDiskDevice(storeMap, oldDisks, server.getDiskDevices(), vm.getVdcId(),
									vendor.getId(), serverId, context.getTarget());
							vm.setName(server.getName());
							vm.setDisk(server.getDisk());
							vm.setCpu(server.getCpu());
							vm.setMemory(server.getMemory());
							if (null != vm.getIsTemplate() && vm.getIsTemplate()) {
								List<Image> images = imageRepository.listByTemplate(vm.getId(), vendor.getId());
								for (Image image : images) {
									image.setName(server.getName());
									image.setGmtModify(new Date());
									image.setMenderId(context.getTarget());
									imageRepository.update(image);
								}
							}
							break;
						default:
							String jdName = bean.getName();
							if (!StringUtils.isEmpty(jdName)) {
								vm.setName(jdName);
							}
							String jdRemark = bean.getRemark();
							if (!StringUtils.isEmpty(jdRemark)) {
								vm.setRemark(jdRemark);
							}
							break;
						}
						cloudServerRepository.update(vm);
						// 更新资源信息
						serverOperationHelper.updateResource(vm, vendor, context);
					}
					event = new ResourceEvent(vm.getId(), "重新配置虚拟机", result.isSuccess() ? "成功" : "失败",
							context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
					resourceEventRepository.save(event);
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), result.getMessage(), operate,
							MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
					// 向堡垒机发送修改消息
					if (vm.getVendorType().equals(CloudProvider.VMWARE.name())) {
						sendUpdateMsgToShterm(vm, oldName);
					}
				} catch (Exception e) {
					logger.error("modify cloud server error:{}", e);
					resourceEventPublisher.send(new OperateResult(false, "编辑虚拟机失败", operate,
							MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
				}
			}).start();
			return new BocloudResult(true, "任务已下发，正在执行...");

		} catch (Exception e) {
			logger.error("Modify cloudServer fail:{}", e.getMessage());
			return new BocloudResult(false, e.getMessage());
		}
	}

	/**
	 * @param oldName
	 * @return void
	 * @Author: lxy
	 * @Description: 向堡垒机发送修改消息
	 * @Date 2021/5/16 17:29
	 * @Param vm
	 * @throws:
	 **/
	private void sendUpdateMsgToShterm(CloudServer vm, String oldName) {
		List<String> ips = new ArrayList<>();
		if (null != vm.getPrivateIps()) {
			getIps(vm.getPrivateIps(), ips);
			for (String ip : ips) {
				JSONObject jsonObject = new JSONObject();
				jsonObject.put("name", vm.getName());
				jsonObject.put("oldName", oldName);
				jsonObject.put("privateIps", ip);
				amqpTemplate.convertAndSend("update.shterm.queue", jsonObject);
				logger.info("send rabbitmq topic is : {} success ，message is ：{}", "update.shterm.queue",
						jsonObject.toJSONString());
			}
		}
	}

	@Override
	public BocloudResult remove(Long id, VmDeleteParam vmDeleteParam, RequestContext context) {
		String path = CloudServer.class.getSimpleName() + "_" + id;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			CloudServer server = cloudServerRepository.get(id);
			Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
			if (server.getStatus().equals(BocloudStatus.Server.SYNSEXCEPTION.name())) {
				return new BocloudResult(false, "同步异常的虚拟机不可以删除!");
			}
			Boolean deletePublicIp = false;
			Boolean deleteVolume = false;
			CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
			Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
			// AWS虚拟机状态检查 更新虚拟机配置的弹性IP
			if (CloudProvider.AWS.name().equals(vendor.getType())
					|| CloudProvider.ALIYUN.name().equals(vendor.getType())) {
				if (!"STOPPED".equals(server.getStatus())) {
					return new BocloudResult(false, "虚拟机非关机状态，请关机后再进行此操作");
				}
				if (null != server.getTerminationProtected() && server.getTerminationProtected()) {
					return new BocloudResult(false, "此虚拟机具有终止保护，无法终止。请关闭终止保护再进行此操作");
				}
				// 应产品需要 删除虚机时如果该虚机绑定浮动IP 则自动解绑，不能因为绑定浮动IP不让删除虚机 该代码先注释掉（后续有问题可讨论）
				// List<ElasticIp> elasticIps =
				// elasticIpRepository.listByIid(server.getInstanceId());
				// if (!ListTool.isEmpty(elasticIps)) {
				// return new BocloudResult(false, "虚拟机下存在弹性IP，请先取消关联后再进行此操作");
				// }
			}
			if (CloudProvider.HMC.name().equals(vendor.getType())) {
				HmcPartition hmcPartition = hmcPartitionRepository.getByUuid(server.getUuid());
				Optional.ofNullable(hmcPartition).orElseThrow(() -> new Exception("HMC分区不存在"));
				return hmcPartitionService.remove(hmcPartition.getId(), new ArrayList<>(), new ArrayList<>(), context);
			} else if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
				if (StringUtils.isNotEmpty(server.getProps())
						&& JSON.parseObject(server.getProps()).containsKey("taskStatus")
						&& "deleting".equals(JSON.parseObject(server.getProps()).getString("taskStatus"))) {
					return new BocloudResult(false, "该虚拟机正在执行删除操作，请勿重复执行!");
				}
			} else if (CloudProvider.ALIYUN.name().equals(vendor.getType())) {
				if (!BocloudStatus.Server.STOPPED.name().equalsIgnoreCase(server.getStatus())) {
					return new BocloudResult(false, "【 " + server.getName() + "】请先关机再进行此操作！ ");
				}
			}
			if (CloudProvider.HUAWEI.name().equals(vendor.getType())) {
				if (null != vmDeleteParam && null != vmDeleteParam.getDeletePublicIp()) {
					deletePublicIp = vmDeleteParam.getDeletePublicIp();
				}
				if (null != vmDeleteParam && null != vmDeleteParam.getDeleteVolume()) {
					deleteVolume = vmDeleteParam.getDeleteVolume();
				}
			}
			// 更新虚拟机挂载的磁盘
			List<Volume> volumes = volumeRepository.listByServerId(id, vendor.getId(), false);
			if (CloudProvider.AWS.name().equals(vendor.getType())) {
				// aws特性
			} else {
				for (Volume volume : volumes) {
					if ("/dev/vda".equals(volume.getDevice()) || "/dev/sda".equals(volume.getDevice())) {
						List<Snapshot> snapshots = snapshotRepository.listByVolumeId(volume.getVolumeUuid(),
								vendor.getId());
						if (!ListTool.isEmpty(snapshots)) {
							return new BocloudResult(false, "根磁盘下存在快照，请先删除快照再进行此操作");
						}
					}
				}
			}
			// 重置虚拟机状态
			server.setStatus("DELETING");
			server.setMenderId(context.getTarget());
			cloudServerRepository.update(server);
			logger.info("虚拟机当前状态：{}", server.getStatus());
			Boolean finalDeletePublicIp = deletePublicIp;
			Boolean finalDeleteVolume = deleteVolume;
			new Thread(() -> {
				String operate = vendor.getType().toLowerCase() + ".vm";
				String content = "虚拟机【" + server.getName() + "】删除失败";
				if (null != server.getIsTemplate() && server.getIsTemplate()) {
					operate = vendor.getType().toLowerCase() + ".template";
					content = "虚拟机模板【" + server.getName() + "】删除失败";
				}
				BocloudResult removeResult = new BocloudResult(false, "删除失败");
				try {
					ResourceEvent event = null;
					if (!server.getStatus().equals(BocloudStatus.Server.SYNSEXCEPTION.name())) {
						BocloudResult result = new BocloudResult(true, "");
						// 当虚拟机instanceId为空时，说明数据库数据状态为创建中可直接删除
						if (!StringUtils.isEmpty(server.getInstanceId())) {
							if (CloudProvider.HUAWEI.name().equals(vendor.getType())) {
								server.setDeletePublicip(finalDeletePublicIp);
								server.setDeleteVolume(finalDeleteVolume);
								result = serverDriver.remove(server.getInstanceId(), finalDeletePublicIp,
										finalDeleteVolume, vendor.getUuid(), server.getRegionId());
							} else if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
								// 如果是Powervc平台，支持删除虚拟机的时候选择删除那些卷
								List<Volume> serverVolumes = volumeRepository.listVolumeByServerId(server.getId());
								for (Volume serverVolume : serverVolumes) {
									VolumeModel volumeModel = new VolumeModel();
									volumeModel.setVolumeUuid(serverVolume.getVolumeUuid());
									volumeModel.setDeleteWithInstance(vmDeleteParam.getVolumeIds().size() != 0
											&& vmDeleteParam.getVolumeIds().contains(serverVolume.getId()));
									result = serverDriver.retachVolume(vendor.getUuid(), null, server.getInstanceId(),
											volumeModel);
									if (result.isFailed()) {
										logger.error("设定卷跟随虚拟机删除失败:" + result.getMessage());
										break;
									}
								}
								// 所有要删除的卷都处理好了，再执行下面的删除操作
								if (result.isSuccess()) {
									result = serverDriver.remove(server.getInstanceId(), server.getName(),
											vendor.getUuid(), null);
								}
							} else {
								result = serverDriver.remove(server.getInstanceId(), server.getName(), vendor.getUuid(),
										server.getRegionId());
							}
						}
						if (result.isSuccess()) {
							if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
								removeResult = serverOperationHelper.remove(id, vmDeleteParam.getVolumeIds(), vendor,
										server, event, context, false);
							} else {
								Boolean isDeletePublicIp = false;
								if (null != vmDeleteParam && null != vmDeleteParam.getDeletePublicIp()) {
									isDeletePublicIp = vmDeleteParam.getDeletePublicIp();
								}
								removeResult = serverOperationHelper.remove(id, null, vendor, server, event, context,
										isDeletePublicIp);
							}
							event = new ResourceEvent(id, "虚拟机删除", "成功", context.getTarget(), new Date(), "VM",
									vendor.getId(), context.getCatalog());
							content = "虚拟机【" + server.getName() + "】删除成功";
							if (null != server.getIsTemplate() && server.getIsTemplate()) {
								content = "虚拟机模板【" + server.getName() + "】删除成功";
							}
						} else {
							if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
								JSONObject props = JSON.parseObject(server.getProps());
								props.remove("taskStatus");
								server.setProps(props.toJSONString());
								cloudServerRepository.update(server);
							}
							event = new ResourceEvent(id, "虚拟机删除", "失败", context.getTarget(), new Date(), "VM",
									vendor.getId(), context.getCatalog());
							content = "虚拟机【" + server.getName() + "】删除失败!" + result.getMessage();
						}
						resourceEventRepository.save(event);
					} else {
						content = "虚拟机【" + server.getName() + "】删除失败";
					}
					// 发送给云平台统计队列对云平台重新统计
					JSONObject jsonObject = new JSONObject();
					jsonObject.put(Common.VENDORID, vendor.getId());
					amqpTemplate.convertAndSend("vendor.statistics.queue", jsonObject);
					resourceEventPublisher.send(new OperateResult(removeResult.isSuccess(), content, operate,
							MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));

				} catch (Exception e) {
					logger.error("删除虚拟机失败", e);
					resourceEventPublisher.send(new OperateResult(false, content, operate,
							MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
				}
			}).start();
			if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
				JSONObject props = StringUtils.isEmpty(server.getProps()) ? new JSONObject()
						: JSON.parseObject(server.getProps());
				props.put("taskStatus", "deleting");
				server.setProps(props.toJSONString());
				cloudServerRepository.update(server);
			}
			return new BocloudResult(true, "删除任务已下发，正在执行...");
		} catch (Exception e) {
			logger.error("remove CloudServer fail:", e);
			return new BocloudResult(false, e.getMessage());
		}
	}

	/**
	 * @param ips
	 * @return void
	 * @Author: lxy
	 * @Description: privateIps 中获取所有ip
	 * @Date 2021/5/16 17:30
	 * @Param privateIps
	 * @throws:
	 **/
	private void getIps(String privateIps, List<String> ips) {
		List<JSONObject> privateIpsList = JSONArray.parseArray(privateIps, JSONObject.class);
		if (ListTool.isEmpty(privateIpsList)) {
			return;
		}
		for (JSONObject json : privateIpsList) {
			String address = json.getString("address");
			if (StringUtils.isEmpty(address)) {
				continue;
			}
			ips.add(address);
		}
	}

	public BocloudResult syncCmdb(CloudServer server, String operator) {
		try {
			// 同步到cmdb 政务云CMDB
			List<CmdbInfo> cmdbInfos = Lists.newArrayList();
			cmdbInfos.add(CmdbInfoConvertor.getItsmInfo(server, operator, null));
			CmdbModel cmdbModel = CmdbInfoConvertor.getCmdbModel(ModuleCode.VM.name(), cmdbInfos);
			logger.info("sync data:" + JSON.toJSONString(cmdbModel));
			amqpTemplate.convertAndSend("cloud.cmdb.message.queue",
					JSONObject.parseObject(JSONObject.toJSONString(cmdbModel)));
			return new BocloudResult(true, "数据同步成功！");
		} catch (AmqpException e) {
			logger.error("同步数据到CMDB异常：" + e.getMessage());
			return new BocloudResult(false, "数据同步失败：" + e.getMessage());
		}
	}

	public BocloudResult changeServerOrderStatus(CloudServer server, String result, RequestContext context) {
		try {
			OrderMessage message = new OrderMessage(server.getUuid(), OrderMessage.Operation.Cancelation,
					OrderItemStatus.UnsubscribeSuccess, null, result, null, null, null,
					ResourceCategory.Computer.name(), context);
			List<QuotaBean> quotas = new ArrayList<>();
			quotas.add(new QuotaBean(server.getVendorType().toLowerCase() + ".standard.server", 1));
			quotas.add(new QuotaBean("meta.cpu", server.getCpu()));
			quotas.add(new QuotaBean("meta.mem", server.getMemory().intValue()));
			quotas.add(new QuotaBean("meta.disk", server.getDisk()));
			message.setQuotas(quotas);
			message.setCategory(ResourceCategory.Computer.name());
			amqpTemplate.convertAndSend("resource.result.queue", message);
			return new BocloudResult(true, "订单状态更新成功！");
		} catch (Exception e) {
			logger.error("订单状态更新失败：" + e.getMessage());
			return new BocloudResult(false, "订单状态更新失败：" + e.getMessage());
		}
	}

	public BocloudResult changeVolumeOrderStatus(Volume volume, RequestContext context) {
		try {
			// 修改虚机订单状态
			if (!org.springframework.util.StringUtils.isEmpty(volume.getUuid())) {
				OrderMessage orderMessage = new OrderMessage(volume.getUuid(), OrderMessage.Operation.Cancelation,
						OrderItemStatus.UnsubscribeSuccess, null, null, null, null, new ArrayList<>(),
						ResourceCategory.Storage.name(), context);
				orderMessage.setCategory(ResourceCategory.Storage.name());
				List<QuotaBean> quotas = new ArrayList<>();
				CloudProvider provider = CloudProvider.valueOf(volume.getVendorType());
				switch (provider) {
				case HUAWEI:
					quotas.add(new QuotaBean("huawei.stanadard.cbs", 1));
					break;
				case TIANYI:
					quotas.add(new QuotaBean("tianyi.standard.volume", 1));
					break;
				default:
					break;
				}
				quotas.add(new QuotaBean("meta.disk", volume.getSize()));
				orderMessage.setQuotas(quotas);
				logger.info("云硬盘退订 orderMessage ： " + JSON.toJSONString(orderMessage));
				amqpTemplate.convertAndSend("resource.result.queue", orderMessage);
			}
			return new BocloudResult(true, "云硬盘订单状态更新成功");
		} catch (Exception e) {
			logger.error("订单状态更新失败：" + e.getMessage());
			return new BocloudResult(true, "订单状态更新失败：" + e.getMessage());
		}
	}

	@Override
	public BocloudResult batchRemove(List<Long> ids, RequestContext context) {
		return batchAction(ids, context, ServerAction.DELETE, "删除");
	}

	@Override
	public BocloudResult<CloudServer> detail(Long id) {
		try {
			CloudServer server = cloudServerRepository.query(id);
			Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
			// 设置虚拟机归属
			if (null != server.getOwnerId() && 0L != server.getOwnerId()) {
				BocloudResult<User> ownerDetail = smsUserService.detail(server.getOwnerId());
				User owner = ownerDetail.getData();
				if (owner != null) {
					server.setOwnerName(owner.getName());
				}
			}
			if (null != server.getMenderId() && 0L != server.getMenderId()) {
				BocloudResult<User> menderDetail = smsUserService.detail(server.getMenderId());
				User mender = menderDetail.getData();
				if (mender != null) {
					server.setMenderName(mender.getName());
				}
			}
			if (null != server.getCreatorId() && 0L != server.getCreatorId()) {
				BocloudResult<User> creatorDetail = smsUserService.detail(server.getCreatorId());
				User creator = creatorDetail.getData();
				if (creator != null) {
					server.setCreatorName(creator.getName());
				}
			}
			if (null != server.getProjectId() && 0L != server.getProjectId()) {
				BocloudResult<Project> projectResult = smsProjectService.detail(server.getProjectId());
				if (projectResult.isFailed() || null == projectResult.getData()) {
					return new BocloudResult(false, projectResult.getMessage());
				}
				Project project = projectResult.getData();
				if (null != project) {
					server.setProjectName(project.getName());
				}
			}
			if (null != server.getBusinessId() && 0L != server.getBusinessId()) {
				BocloudResult<Business> businessDetail = smsBusinessService.detail(server.getBusinessId());
				Business business = businessDetail.getData();
				if (business != null) {
					server.setBusinessName(business.getName());
				}
			}
			// 设置模板名称
			if (null != server.getTemplateId()) {
				CloudServer temp = cloudServerRepository.get(server.getTemplateId());
				if (null != temp) {
					server.setTemplate(temp.getName());
					server.setTemplateUuid(temp.getInstanceId());
				}
			}
			if (!StringUtils.isEmpty(server.getTenantUuid())) {
				OSTenant osTenant = osTenantRepository.getByTenantUuid(server.getTenantUuid(), server.getVendorId());
				if (null != osTenant) {
					server.setOsTenantName(osTenant.getName());
				}
			}
			// 设置主机名称
			Server host = serverRepository.query(server.getHostId());
			if (null != host) {
				server.setHostName(host.getName());
				server.setClusterName(host.getClusterName());
				server.setVdcName(host.getVdcName());
			}
			// 查询是否存在定时快照任务
			List<SnapshotTask> tasks = snapshotTaskRepository.listByServerId(server.getId());
			server.setHasSnapshotTask(!ListTool.isEmpty(tasks));
			CloudProvider provider = CloudProvider.valueOf(server.getVendorType());
			// 设置浮动IP
			if (CloudProvider.TIANYI == provider || CloudProvider.TENCENT == provider
					|| CloudProvider.QCLOUD == provider) {
				FloatingIp floatingIp = floatingIpRepository.getByInstanceId(server.getInstanceId());
				if (null != floatingIp) {
					server.setFipId(floatingIp.getId());
					server.setFloatingIp(floatingIp.getFloatingIpAddress());
				}
			} else if (CloudProvider.ALIYUN == provider) {
				List<ElasticIp> elasticIps = elasticIpRepository.listByIid(server.getInstanceId(),
						server.getVendorId());
				if (!ListTool.isEmpty(elasticIps)) {
					server.setFipId(elasticIps.get(0).getId());
					server.setFloatingIp(elasticIps.get(0).getPublicIp());
				}
			} else if (CloudProvider.HUAWEI == provider) {
				ElasticIp elasticIp = elasticIpRepository.queryByAllocationId(server.getInstanceId());
				if (null != elasticIp) {
					server.setFipId(elasticIp.getId());
					server.setFloatingIp(elasticIp.getPublicIp());
				}
			} else {
				FloatingIp floatingIp = floatingIpRepository.listByServerId(server.getInstanceId());
				if (null != floatingIp) {
					server.setFipId(floatingIp.getId());
					server.setFloatingIp(floatingIp.getFloatingIpAddress());
					Network network = networkRepository.query(floatingIp.getNetworkId());
					if (null != network) {
						server.setFloatingIpName(network.getName());
					}
				}
			}
			// 设置安全组名称
			String sgroupNames = "";
			List<SecurityGroup> sGroups = securityGroupRepository.listByServerId(server.getId());
			for (SecurityGroup group : sGroups) {
				sgroupNames += group.getName() + ",";
			}
			if (sgroupNames.length() > 0) {
				sgroupNames = sgroupNames.substring(0, sgroupNames.length() - 1);
			}
			server.setSgroupNames(sgroupNames);
			// 设置快照数量
			List<Snapshot> snapshots = snapshotRepository.listByVMid(server.getId());
			server.setSnapshotCount(snapshots.size());
			// 网络适配器
			List<NetworkCard> cards = networkCardRepository.listByHost(id, "VM");
			server.setNetcards(cards);
			server.setPassword(null);
			Flavor flavor = flavorRepository.getByFlavorId(server.getFlavorUuid(), server.getVendorId(),
					server.getRegionId());
			if (null != flavor) {
				server.setFlavorName(flavor.getName());
				server.setFlavor(flavor);
			}
			Image image = imageRepository.getByImageUuid(server.getImageUuid());
			if (CloudProvider.AZURE.name().equals(server.getVendorType())) {
				if (ObjectUtils.isEmpty(image)) {
					if (!StringUtils.isEmpty(server.getOsName()) && !StringUtils.isEmpty(server.getOsVersion())) {
						server.setImageName(server.getOsName() + "(" + server.getOsVersion() + ")");
					}
				} else {
					server.setImageName(image.getName());
				}
			} else {
				server.setImageName(null != image ? image.getName() : server.getOsVersion());
			}
			if (!StringUtils.isEmpty(server.getRegion())) {
				Region region = regionRepository.getByName(server.getRegion(), server.getVendorId());
				if (null != region) {
					server.setRegionName(region.getName());
				}
			}
			if (!StringUtils.isEmpty(server.getZone())) {
				List<Zone> zoneId = zoneRepository.listByZoneId(server.getZone(), server.getVendorId());
				if (null != zoneId && zoneId.size() > 0) {
					server.setZoneName(zoneId.get(0).getName());
				}
			}
			List<Volume> volumes = volumeRepository.listByServerId(server.getId(), server.getVendorId(), false);
			Integer total = 0;
			if (CloudProvider.JDCLOUD == provider) {
				// 京东云系统盘固定默认40
				total = 40;
			}
			if (!ListTool.isEmpty(volumes)) {
				for (Volume volume : volumes) {
					total += volume.getSize() == null ? 0 : volume.getSize();
				}
				server.setTotalDisks(total);
			}
			if (CloudProvider.QCLOUD == provider || CloudProvider.PQCLOUD == provider
					|| CloudProvider.AWS == provider) {
				List<String> keyPairNames = new ArrayList<String>();
				List<ServerKeypair> listByServerId = serverKeyPairRepository.listByServerId(server.getId());
				for (ServerKeypair serverKeypair : listByServerId) {
					Keypair keypair = keyPairRepository.query(serverKeypair.getKeypairId());
					if (null != keypair) {
						keyPairNames.add(keypair.getName());
					}
				}
				server.setKeypairName(JSON.toJSONString(keyPairNames));
			}
			// 虚机标签
			ServerLabel serverLabel = serverLabelRepository.listByTarget(server.getId(), "VM", server.getVendorId());
			if (null != serverLabel) {
				List<JSONObject> parseArray = JSON.parseArray(serverLabel.getContent(), JSONObject.class);
				if (!ListTool.isEmpty(parseArray)) {
					for (int i = parseArray.size() - 1; i >= 0; i--) {
						JSONObject jsonObject = parseArray.get(i);
						String key = jsonObject.getString("key");
						String value = jsonObject.getString("value");
						Label label = labelRepository.getLabelByName(key);
						if (null != label) {
							List<String> contentArray = JSON.parseArray(label.getContent(), String.class);
							if (null != contentArray && !contentArray.contains(value)) {
								parseArray.remove(jsonObject);
							}
						} else {
							parseArray.remove(jsonObject);
						}
					}
					serverLabel.setContent(JSON.toJSONString(parseArray));
					serverLabelRepository.update(serverLabel);
				}
				server.setResourceLabel(serverLabel.getContent());
			}
			List<Volume> volumesList = volumeRepository.listByServerId(server.getId(), server.getVendorId(), true);
			server.setBootFromVolume(!ListTool.isEmpty(volumesList));
			// Powervc虚拟机需要从driver中获取最新的RMC链接状态
			if (CloudProvider.POWERVC == provider && !StringUtils.isEmpty(server.getInstanceId())) {
				if (BocloudStatus.Server.STOPPED.name().equals(server.getStatus())) {
					// 如果虚拟机是关机状态，则直接认为rmc连接状态活动，不需要再重新查询Driver
					JSONObject props = StringUtils.isEmpty(server.getProps()) ? new JSONObject()
							: JSON.parseObject(server.getProps());
					props.put("rmcStatus", "active");
					server.setProps(props.toJSONString());
				} else {
					CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
					if (vendor != null) {
						BocloudResult bocloudResult = serverDriver.detail(server.getInstanceId(), vendor.getUuid(),
								null);
						if (bocloudResult.isSuccess()) {
							ServerModel serverModel = (ServerModel) bocloudResult.getData();
							if (serverModel != null) {
								server.setProps(serverModel.getProps());
							}
						}
					}
				}
			} else if (CloudProvider.TIANYI == provider && !StringUtils.isEmpty(server.getInstanceId())) {
				List<String> privateIps = JSONArray.parseArray(server.getPrivateIps(), String.class);
				List<NetworkCard> networkCards = new ArrayList<>();
				NetworkCard networkCard = null;
				for (String privateIp : privateIps) {
					networkCard = new NetworkCard();
					FloatingIp floatingIp = floatingIpRepository.getByFixedIpAddress(privateIp, server.getVendorId());
					if (floatingIp != null && !"".equals(floatingIp)) {
						networkCard.setNetworkcardUuid(floatingIp.getNetworkCardUuid());
						networkCard.setFloatingIp(floatingIp.getFloatingIpAddress());
						networkCard.setFloatingIpUuid(floatingIp.getFloatingIpUuid());
					}
					networkCard.setIpAddress(privateIp);
					networkCards.add(networkCard);
				}
				server.setNetcards(networkCards);
			}
			return new BocloudResult(true, server, "查询成功!");
		} catch (Exception e) {
			logger.error("get cloudserver failure:", e);
			return new BocloudResult(false, "查询失败!");
		}
	}

	@Override
	public BocloudResult basic(Long id) {
		try {
			CloudServer server = cloudServerRepository.query(id);
			return new BocloudResult(true, server, "查询成功!");
		} catch (Exception e) {
			logger.error("get cloudserver failure:", e);
			return new BocloudResult(false, "查询失败!");
		}
	}

	@Override
	public BocloudResult start(Long serverId, RequestContext context) {
		return this.handleAction(serverId, context, ServerAction.START);
	}

	public BocloudResult batchAction(List<Long> idArray, RequestContext context, ServerAction action, String message) {
		// 获取要开启的虚拟机
		if (ListTool.isEmpty(idArray)) {
			return new BocloudResult(false, "没有需要" + message + "的机器！", "没有需要" + message + "的机器！");
		}
		try {
			for (Long id : idArray) {
				CloudServer server = cloudServerRepository.query(id);
				if (null == server) {
					continue;
				}
				BocloudResult result = null;
				switch (action) {
				case START:
					result = start(id, context);
					break;
				case STOP:
					result = stop(id, context);
					break;
				case REBOOT:
					result = restart(id, context);
					break;
				case DELETE:
					result = remove(id, null, context);
					break;
				default:
					result = new BocloudResult(false, "暂不支持该类操作");
					break;
				}
				if (result.isFailed()) {
					resourceEventPublisher.send(new OperateResult(false,
							"【" + server.getName() + "】" + message + "失败:" + result.getMessage(),
							server.getVendorType().toLowerCase() + ".vm",
							MapTools.simpleMap(Common.VENDORID, server.getVendorId()), OperateCategory.ResourceEvent,
							context));
				}
			}
		} catch (Exception e) {
			logger.error("batch action server fail:", e);
			return new BocloudResult(false, "批量" + message + "任务已下发失败");
		}
		return new BocloudResult(true, "批量" + message + "任务已下发，正在执行...");
	}

	@Override
	public BocloudResult batchStart(List<Long> ids, RequestContext context) {
		return batchAction(ids, context, ServerAction.START, "启动");
	}

	@Override
	public BocloudResult batchReboot(List<Long> ids, RequestContext context) {
		return batchAction(ids, context, ServerAction.REBOOT, "重启");
	}

	@Override
	public BocloudResult batchStop(List<Long> ids, RequestContext context) {
		return batchAction(ids, context, ServerAction.STOP, "停止");
	}

	@Override
	public BocloudResult restart(Long serverId, RequestContext context) {
		return this.handleAction(serverId, context, ServerAction.REBOOT);
	}

	@Override
	public BocloudResult softRestart(Long serverId, RequestContext context) {
		return this.handleAction(serverId, context, ServerAction.SOFTREBOOT);
	}

	public BocloudResult deallocate(Long serverId, RequestContext context) {
		return this.handleAction(serverId, context, ServerAction.DEALLOCATE);
	}

	@Override
	public BocloudResult stop(Long serverId, RequestContext context) {
		return this.handleAction(serverId, context, ServerAction.STOP);
	}

	@Override
	public BocloudResult pause(Long serverId, RequestContext context) {
		return this.handleAction(serverId, context, ServerAction.PAUSE);
	}

	@Override
	public BocloudResult suspend(Long serverId, RequestContext context) {
		return this.handleAction(serverId, context, ServerAction.SUSPEND);
	}

	@Override
	public BocloudResult resume(Long serverId, RequestContext context) {
		return this.handleAction(serverId, context, ServerAction.RESUME);
	}

	@Override
	public BocloudResult active(Long serverId, RequestContext context) {
		return this.handleAction(serverId, context, ServerAction.ACTIVE);
	}

	@Override
	public BocloudResult backup(Long id, RequestContext context) {
		return new BocloudResult(true, null, "调用成功，但是TODO:");
	}

	@Override
	public BocloudResult recovery(Long serverId, RequestContext context) {
		return this.handleAction(serverId, context, ServerAction.RECOVERY);
	}

	/**
	 * 处理虚拟机状态
	 *
	 * @param serverId
	 * @param context
	 * @param action
	 * @return
	 */
	private BocloudResult handleAction(Long serverId, RequestContext context, ServerAction action) {
		return serverOperationHelper.handleAction(serverId, context, action);
	}

	@Override
	public BocloudResult createInResPool(VmGenericParam params, RequestContext context) {
		// 虚拟机名
		String name = params.getName();
		// 数据中心ID
		Long vdcId = params.getVdcId();
		// 主机ID
		Long hostId = params.getHostId();
		// 资源池ID
		Long resPoolId = params.getResPoolId();
		// 数据存储ID
		Long dsId = params.getDsId();
		// 系统类别
		String osCategory = params.getOsCategory();
		// 系统名称
		String osName = params.getOsName();
		// cpu
		Integer cpu = params.getCpu();
		// 内存
		BigDecimal memory = params.getMemory();
		// 磁盘
		Integer disk = params.getDisk();
		// 磁盘单位
		String diskUnit = params.getDiskUnit();
		// 描述
		String remark = params.getRemark();
		// 数据存储中的镜像路径
		String isoPath = params.getIsoPath();
		// 资源池所属类别
		String poolOwner = params.getPoolOwner();
		// 命名规则ID
		Long nameRuleId = params.getNameRuleId();
		// 标签
		List<Long> labels = params.getLabelIds();
		ServerModel model = new ServerModel(name, cpu, memory, disk, null);
		try {
			if (null != nameRuleId && 0L != nameRuleId) {
				JSONObject jsonObject = new JSONObject();
				jsonObject.put("userId", context.getTarget());
				jsonObject.put("tenantId", context.getTenant());
				BocloudResult result = nameRuleService.generate(nameRuleId, jsonObject);
				if (result.isFailed()) {
					return new BocloudResult(false, "虚拟机名称生成失败");
				}
				name = String.valueOf(result.getData());
			}
			// 数据中心
			Vdc vdc = vdcRepository.query(vdcId);
			Optional.ofNullable(vdc).orElseThrow(() -> new Exception("数据中心不存在"));
			model.setVdcName(vdc.getName());
			if (cloudServerRepository.exists(name, vdc.getVendorId())) {
				return new BocloudResult(false, "此名称已存在!");
			}
			// 云供应商
			CloudVendor vendor = cloudVendorRepository.query(vdc.getVendorId());
			Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
			// 宿主机
			Server server = serverRepository.query(hostId);
			Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
			model.setHostName(server.getName());
			// 宿主机资源池下创建虚拟机
			VmResourcePool vmResourcePool = resourcePoolRepository.query(resPoolId);
			Optional.ofNullable(vmResourcePool).orElseThrow(() -> new Exception("指定的资源池不存在"));
			model.setResPoolName(vmResourcePool.getName());
			// 集群资源池下创建虚拟机
			if ("CLUSTER".equals(poolOwner)) {
				Cluster cluster = clusterRepository.query(vmResourcePool.getOwner());
				model.setClusterName(cluster.getName());
			}
			// 数据存储
			DataStore dataStore = dataStoreRepository.query(dsId);
			Optional.ofNullable(dataStore).orElseThrow(() -> new Exception("指定的数据存储不存在"));
			model.setDatastore(dataStore.getName());
			model.setOsCategory(osCategory);
			model.setOsName(osName);
			model.setDiskUnit(diskUnit);
			model.setRemark(remark);
			model.setIsoPath(isoPath);
			if (!ListTool.isEmpty(params.getNicAdapters())) {
				List<NicAdapterModel> nicList = params.getNicAdapters();
				if (!ListTool.isEmpty(nicList)) {
					for (NicAdapterModel nic : nicList) {
						PortGroup portGroup = portGroupRepository.query(nic.getNetId());
						Optional.ofNullable(portGroup).orElseThrow(() -> new Exception("虚拟网卡不存在"));
						nic.setNetName(portGroup.getName());
					}
				}
				model.setNicAdapters(nicList);
			}
			CloudServer cloudServer = JSONObject.parseObject(JSONObject.toJSONString(model), CloudServer.class);
			// 保存数据
			cloudServer.setStatus(BocloudStatus.Server.BUILDING.name());
			cloudServer.setIsTemplate(false);
			cloudServer.preSave(context.getTarget(), context.getTarget(), vendor.getId(), hostId, model.getVdcId(),
					null, context.getTenant(), context.getProject());
			cloudServer.setResourceId(IDFactory.instance().uuid());
			cloudServer.setVendorType(vendor.getType());
			cloudServer.setRecycle(false);
			cloudServer.setCatalog(context.getCatalog());
			cloudServer.setPswd(model.getPassword());
			cloudServerRepository.save(cloudServer);
			taskExecutor.execute(() -> {
				String operate = vendor.getType().toLowerCase() + ".vm";
				String content = "虚拟机创建失败";
				try {
					logger.info("Create vm in resource pool start...");
					BocloudResult result = serverDriver.createInResPool(vendor.getUuid(), null, model);
					if (result.isSuccess()) {
						ServerModel serverModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()),
								ServerModel.class);
						BeanUtils.copyProperties(serverModel, cloudServer);
						String state = serverModel.getStatus();
						if ("poweredOn".equalsIgnoreCase(state)) {
							cloudServer.setStatus(BocloudStatus.Server.RUNNING.name());
						} else if ("poweredOff".equalsIgnoreCase(state)) {
							cloudServer.setStatus(BocloudStatus.Server.STOPPED.name());
						} else if ("suspended".equalsIgnoreCase(state)) {
							cloudServer.setStatus(BocloudStatus.Server.SUSPENDED.name());
						} else {
							cloudServer.setStatus(BocloudStatus.Server.EXCEPTION.name());
						}
						cloudServer.setResPoolId(resPoolId);
						cloudServer.setHostId(hostId);
						cloudServer.setVdcId(vdcId);
						// 更新虚拟机数据
						cloudServerRepository.update(cloudServer);
						// 保存标签信息
						if (!ListTool.isEmpty(labels)) {
							List<ServerLabel> serverLabels = Lists.newArrayList();
							for (Long labelId : labels) {
								serverLabels.add(new ServerLabel(cloudServer.getId(), labelId, "VM", vendor.getId()));
							}
							if (!ListTool.isEmpty(serverLabels)) {
								serverLabelRepository.batchSave(serverLabels);
							}
						}
						List<VolumeModel> diskDevices = serverModel.getDiskDevices();
						if (!ListTool.isEmpty(diskDevices)) {
							for (VolumeModel volume : diskDevices) {
								Volume diskVol = new Volume();
								BeanUtils.copyProperties(volume, diskVol);
								diskVol.preSave(context.getTarget(), context.getTarget(), 0L, vendor.getId());
								diskVol.setServerId(cloudServer.getId());
								diskVol.setVolumeUuid(IDFactory.instance().uuid());
								volumeRepository.save(diskVol);
							}
						}
						// 虚拟机网卡设备
						List<NetworkCardModel> netcards = serverModel.getNetcards();
						List<NetworkCard> cards = Lists.newArrayList();
						if (!ListTool.isEmpty(netcards)) {
							cards = JSONObject.parseArray(JSONArray.toJSONString(netcards), NetworkCard.class);
						}
						// 网络与虚拟机关系
						List<NetworkModel> networkModels = serverModel.getNetworks();
						List<Network> networks = Lists.newArrayList();
						if (!ListTool.isEmpty(networkModels)) {
							networks = JSONObject.parseArray(JSONArray.toJSONString(networkModels), Network.class);
						}
						serverOperationHelper.syncSubObject(vdcId, vendor.getId(), cloudServer.getId(),
								serverModel.getStores(), networks, cards, context.getTarget());
						// 保存资源信息
						Resource resource = resourceRepository.query(ResourceCategory.Computer.name(),
								ResourceCatalog.LOGICAL.name(), cloudServer.getId());
						if (null == resource) {
							resource = new Resource(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
									cloudServer.getId(), null, cloudServer.getOsCategory(), vendor.getId());
							resource.preSave(cloudServer.getName(), cloudServer.getStatus(), context.getTarget(),
									context.getTenant());
							resource.setInventory(JSONObject.toJSONString(cloudServer));
							resourceRepository.save(resource);
						} else {
							resource.setMenderId(context.getTarget());
							resource.setGmtModify(new Date());
							resource.setInventory(JSONObject.toJSONString(cloudServer));
							resourceRepository.update(resource);
						}
						content = "虚拟机已创建成功，请在虚拟机列表下的控制台中进行客户机操作系统相关配置";
					} else {
						content = result.getMessage();
						cloudServerRepository.remove(cloudServer.getId(), context.getTarget());
					}
					// 保存资源信息
					ResourceEvent event = null;
					if (result.isSuccess()) {
						event = new ResourceEvent(cloudServer.getId(), "虚拟机创建", "成功", context.getTarget(), new Date(),
								"VM", vendor.getId(), context.getCatalog());
					} else {
						event = new ResourceEvent(cloudServer.getId(), "虚拟机创建", "失败", context.getTarget(), new Date(),
								"VM", vendor.getId(), context.getCatalog());
					}
					logger.info("Create vm in resource pool end...");
					resourceEventRepository.save(event);
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
							MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
				} catch (Exception e) {
					logger.error("Get Message Exception:", e);
					resourceEventPublisher.send(new OperateResult(false, content, operate,
							MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
				}
			});
			return new BocloudResult(true, "创建任务已经下发，正在执行……");
		} catch (Exception e) {
			logger.error("create server error:", e);
			return new BocloudResult(false, "创建失败!");
		}
	}

	@Override
	public BocloudResult exists(String name, Long vendorId) {
		try {
			boolean exists = cloudServerRepository.exists(name, vendorId);
			if (exists) {
				return new BocloudResult(true, "该名称已存在");
			}
			return new BocloudResult(false, "该名称不存在");
		} catch (Exception e) {
			logger.error("Get error message:", e);
			return new BocloudResult(false, "查询失败");
		}
	}

	@Override
	public BocloudResult list(List<Param> params, RequestContext context) {
		try {
			Long subnetId = null;
			Long clusterId = null;
			Long labelId = null;
			if (null == params) {
				params = new ArrayList<>();
			} else {
				for (Param param : params) {
					Map<String, Object> paramMap = param.getParam();
					if (paramMap.containsKey("subnetId")) {
						subnetId = Long.valueOf(paramMap.get("subnetId").toString());
						paramMap.remove("subnetId");
					}
					if (paramMap.containsKey("clusterId")) {
						clusterId = Long.valueOf(paramMap.get("clusterId").toString());
						paramMap.remove("clusterId");
					}
					if (paramMap.containsKey("props")) {
						labelId = Long.valueOf(paramMap.get("props").toString());
						paramMap.remove("props");
					}
				}
			}
			List<CloudServer> list = new ArrayList<>();
			Long tenantId = context.getTenant();
			Long projectId = context.getProject();
			// 当前用户为租户
			if (0 != tenantId) {
				List<Project> projects = smsProjectService.projectsByCondition(context.getTarget(),
						context.getCatalog());
				List<Long> projectIds = new ArrayList<>();
				// 此时查询的是全部用户全部项目的信息
				if (null != projectId && 0L != projectId) {
					projectIds.add(projectId);
				} else if (!ListTool.isEmpty(projects)) {
					projects.forEach(project -> {
						projectIds.add(project.getId());
					});
				} else {
					// 当前用户不属于任何项目，则登录之后查看不到任何虚拟机信息
					projectIds.add(-1L);
				}
				list = this.cloudServerRepository.list(0, 0, params, null, subnetId, null, projectIds, null);
			} else if (null != clusterId) {
				list = this.cloudServerRepository.list(0, 0, clusterId, new ArrayList<>(), null);
			} else {
				list = this.cloudServerRepository.list(0, 0, params, null, labelId, null, null);
			}
			for (CloudServer server : list) {
				// 设置主机名称
				Server host = serverRepository.query(server.getHostId());
				if (null != host) {
					server.setHostName(host.getName());
					server.setClusterName(host.getClusterName());
					server.setVdcName(host.getVdcName());
				}
				// 设置快照数量
				List<Snapshot> snapshots = snapshotRepository.listByVMid(server.getId());
				server.setSnapshotCount(snapshots.size());
				// 设置浮动IP
				FloatingIp floatingIp = floatingIpRepository.listByServerId(server.getInstanceId());
				if (null != floatingIp) {
					server.setFipId(floatingIp.getId());
					server.setFloatingIp(floatingIp.getFloatingIpAddress());
				}
				if (!StringUtils.isEmpty(server.getResourceGroup())) {
					Dictionary dictionary = dictionaryRepository.query(server.getResourceGroup(), "RESOURCE_GROUP");
					server.setResourceGroupName(dictionary.getName());
				}
			}
			return new BocloudResult(true, list, "查询成功");
		} catch (Exception e) {
			logger.error("query error message：", e);
			return new BocloudResult(false, "查询虚拟机信息失败");
		}
	}

	@Override
	public BocloudResult batchClone(String params, RequestContext context) {
		try {
			JSONObject object = JSONObject.parseObject(params);
			Long vendorId = object.getLong(Common.VENDORID);
			List<Long> serverIds = JSONArray.parseArray(object.getString("serverIds"), Long.class);
			if (ListTool.isEmpty(serverIds)) {
				return new BocloudResult(false, "没有要克隆的虚拟机");
			}
			CloudVendor vendor = cloudVendorRepository.query(vendorId);
			Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
			Long ipPoolId = object.getLong("ipPoolId");
			// VCenter分配的虚拟机IP
			List<Ip> ips = Lists.newArrayList();
			List<ProcessResult> processResults = Lists.newArrayList();
			for (Long serverId : serverIds) {
				CloudServer server = cloudServerRepository.query(serverId);
				Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
				if (null != server.getTenantId() && server.getTenantId() > 0) {
					return new BocloudResult(false, "不能对租户的虚拟机进行克隆操作");
				}
				Server host = serverRepository.query(server.getHostId());
				Optional.ofNullable(host).orElseThrow(() -> new Exception("目标宿主机不存在"));
				// 查询模板的网卡
				List<NetworkCard> cards = networkCardRepository.listByHost(server.getId(), "VM");
				if (ListTool.isEmpty(cards)) {
					return new BocloudResult(false, "虚拟机模板上无任何网卡");
				}
				List<NetcardOperation> operations = Lists.newArrayList();
				for (NetworkCard card : cards) {
					NetcardOperation operation = new NetcardOperation();
					operation.setName(card.getName());
					operation.setOperation("EDIT");
					operation.setIpv4PoolId(ipPoolId);
					operation.setLabel(card.getLabel());
					operation.setPortType(card.getPortType());
					operation.setMac(card.getMac());
					operations.add(operation);
				}
				// 分配IP
				BocloudResult bocloudResult = serverOperationHelper.assignIp(vendor, operations);
				List<Ip> ipList = JSONArray.parseArray(JSONObject.toJSONString(bocloudResult.getData()), Ip.class);
				if (bocloudResult.isFailed()) {
					serverOperationHelper.recycleIp(ips, null, vendorId);
					return new BocloudResult(false, bocloudResult.getMessage());
				} else {
					ips.addAll(ipList);
				}
				JSONObject jsonObject = new JSONObject();
				jsonObject.put("name", server.getName() + "_CLONE");
				jsonObject.put("hostname", host.getName());
				jsonObject.put("vmHostName", "bocloud");
				jsonObject.put("remark", server.getRemark());
				jsonObject.put("hostId", host.getId());
				jsonObject.put("operations", JSONObject.toJSON(operations));
				jsonObject.put("templateId", server.getId());
				jsonObject.put("cpu", server.getCpu());
				jsonObject.put("memory", server.getMemory());
				jsonObject.put("disk", server.getDisk());
				jsonObject.put("account", server.getAccount());
				jsonObject.put("password", server.receivePswd());
				List<StoreHost> storeHosts = storeHostRepository.list(host.getId(), "PM");
				Long storeId = storeHosts.get(new Random().nextInt(storeHosts.size())).getStoreId();
				jsonObject.put("storeId", storeId);
				DataStore store = dataStoreRepository.query(storeId);
				if (null == store) {
					serverOperationHelper.recycleIp(ips, null, vendorId);
					return new BocloudResult(false, "宿主机【" + host.getName() + "】下无任何数据存储可用!");
				}
				jsonObject.put("datastore", store.getName());
				ServerBuilder builder = new VMServerBuilder(cloudServerRepository, serverRepository,
						dataStoreRepository, networkRepository, networkCardRepository, portGroupRepository,
						switcherRepository, storeHostRepository, networkHostRepository, ipRepository,
						resourceRepository, resourceEventRepository, volumeRepository, serverLabelRepository,
						serverDriver, context, vendor, resourceEventPublisher, ipPoolRepository, smsTenantService,
						lockFactory, smsProjectService, lvmService, amqpTemplate);
				BocloudResult<ServerModel> result = builder.prepare(jsonObject);
				if (result.isFailed()) {
					// 回收IP
					serverOperationHelper.recycleIp(ips, null, vendor.getId());
					return new BocloudResult(false, "虚拟机【" + server.getName() + "】克隆失败：" + result.getMessage());
				}
				ServerModel model = result.getData();
				processResults.add(new ProcessResult(model, builder, server));
			}
			new Thread(() -> {
				String operate = vendor.getType().toLowerCase() + ".vm";
				logger.info("Batch clone virtual machine start...");
				// 克隆成功的虚拟机
				List<BocloudResult> succList = Lists.newArrayList();
				// 克隆失败的虚拟机
				List<BocloudResult> failList = Lists.newArrayList();
				List<Future<BocloudResult<CloudServer>>> futures = new ArrayList<>();
				try {
					// 保存虚拟机的一些基本信息
					for (ProcessResult processResult : processResults) {
						ServerModel model = processResult.getServerModel();
						CloudServer cloudServer = JSONObject.parseObject(JSONObject.toJSONString(model),
								CloudServer.class);
						cloudServer.setStatus(BocloudStatus.Server.BUILDING.name());
						cloudServer.setIsTemplate(false);
						CloudServer oldServer = processResult.getCloudServer();
						cloudServer.setRegion(oldServer.getRegion());
						cloudServer.setAccount(oldServer.getAccount());
						cloudServer.setPswd(oldServer.receivePswd());
						cloudServer.preSave(context.getTarget(), context.getTarget(), vendor.getId(), model.getHostId(),
								model.getVdcId(), null, context.getTenant(), context.getProject());
						cloudServer.setResourceId(IDFactory.instance().uuid());
						cloudServer.setVendorType(vendor.getType());
						cloudServer.setRecycle(false);
						cloudServerRepository.save(cloudServer);
						processResult.setCloudServer(cloudServer);
					}
					resourceEventPublisher.send(new OperateResult(true, "虚拟机克隆中，请耐心等待", operate,
							MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
					// 执行创建虚拟机的操作
					for (ProcessResult processResult : processResults) {
						futures.add(taskExecutor.submit(new Callable<BocloudResult<CloudServer>>() {
							@Override
							public BocloudResult<CloudServer> call() throws Exception {
								return processResult.getServerBuilder().builder(processResult.getCloudServer());
							}
						}));
					}
					// 获取线程池返回结果
					for (int i = 0; i < futures.size(); i++) {
						BocloudResult<CloudServer> result = futures.get(i).get(1, TimeUnit.HOURS);
						CloudServer cloudServer = result.getData();
						ResourceEvent event = null;
						if (result.isSuccess()) {
							Server host = serverRepository.query(cloudServer.getHostId());
							BocloudResult bocloudResult = new BocloudResult(true,
									"【" + cloudServer.getName() + "】克隆成功【" + result.getMessage() + "】");
							succList.add(bocloudResult);
							event = new ResourceEvent(cloudServer.getId(), "虚拟机克隆", "成功", context.getTarget(),
									new Date(), "VM", vendor.getId(), context.getCatalog());
						} else {
							BocloudResult bocloudResult = new BocloudResult(true,
									"【" + cloudServer.getName() + "】克隆失败【" + result.getMessage() + "】");
							failList.add(bocloudResult);
							event = new ResourceEvent(cloudServer.getId(), "虚拟机克隆", "失败", context.getTarget(),
									new Date(), "VM", vendor.getId(), context.getCatalog());
						}
						resourceEventRepository.save(event);
					}
					// 创建成功的数量
					int success = succList.size();
					// 创建失败的数量
					int fail = failList.size();
					// 发送站内信
					String content = null;
					if (fail == processResults.size()) {
						content = "虚拟机克隆失败，详情如下：\n";
						for (BocloudResult bocloudResult : failList) {
							content += bocloudResult.getMessage() + "\n";
						}
					} else {
						content = "虚拟机克隆成功【" + success + "】个,失败【" + fail + "】个，详情如下：\n";
						for (BocloudResult bocloudResult : succList) {
							content += bocloudResult.getMessage() + "\n";
						}
						for (BocloudResult bocloudResult : failList) {
							content += bocloudResult.getMessage() + "\n";
						}
					}
					resourceEventPublisher.send(new OperateResult(fail == 0, content, operate,
							MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
					logger.info("Batch clone virtual machine end...");
				} catch (Exception e) {
					logger.error("Get Message Exception:", e);
					// 回收IP
					serverOperationHelper.recycleIp(ips, null, vendor.getId());
					resourceEventPublisher.send(new OperateResult(false, "虚拟机克隆失败", operate,
							MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
				}
			}).start();
			return new BocloudResult(true, "虚拟机克隆任务已经下发，正在执行……");
		} catch (Exception e) {
			logger.error("Clone server error:", e);
			return new BocloudResult(false, "虚拟机克隆失败!");
		}
	}

	@Override
	public BocloudResult batchSnapshot(BatchSnapshotParam params, RequestContext context) {
		try {
			List<Long> serverIds = params.getServerIds();
			if (ListTool.isEmpty(serverIds)) {
				return new BocloudResult(false, "未选择任何虚拟机");
			}
			Long vendorId = params.getVendorId();
			CloudVendor vendor = cloudVendorRepository.query(vendorId);
			Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
			new Thread(() -> {
				Long userId = context.getTarget();
				String operate = vendor.getType().toLowerCase() + ".snapshot";
				CloudProvider provider = CloudProvider.valueOf(vendor.getType());
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				String suffix = sdf.format(new Date());
				List<Future<BocloudResult>> futures = new ArrayList<>();
				for (Long serverId : serverIds) {
					futures.add(taskExecutor.submit(() -> {
						CloudServer server = cloudServerRepository.query(serverId);
						Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
						if (null != server.getTenantId() && server.getTenantId() > 0) {
							return new BocloudResult(false, "不能对租户的虚拟机进行快照操作");
						}
						switch (provider) {
						case OPENSTACK:
							if (null != server.getProjectId() && 0L != server.getProjectId()) {
								BocloudResult<Project> projResult = smsProjectService.detail(server.getProjectId());
								if (projResult.isFailed()) {
									return new BocloudResult(false, projResult.getMessage());
								}
								Optional.ofNullable(projResult.getData())
										.orElseThrow(() -> new Exception("虚拟机所在项目不存在"));
							}
							break;
						case VMWARE:
							Server host = serverRepository.query(server.getHostId());
							Optional.ofNullable(host).orElseThrow(() -> new Exception("宿主机不存在"));
							if (null != host.getMaintained() && host.getMaintained()) {
								return new BocloudResult(false, "该虚拟机所在宿主机处于维护模式下，无法执行创建快照任务");
							}
							break;
						case POWERVC:
							if (server.getStatus().equals(BocloudStatus.Server.RUNNING.name())) {
								return new BocloudResult(false, "开机状态的power虚拟机，不允许捕获快照!");
							}
							break;
						default:
							break;
						}
						String snapName = server.getName() + "_snapshot_" + suffix;
						String remark = "Snapshot of vm " + server.getName() + "";
						SnapshotModel model = new SnapshotModel(snapName, remark, null, server.getInstanceId());
						BocloudResult result = serverDriver.snapshot(model, vendor.getUuid(), null);
						if (result.isFailed()) {
							return new BocloudResult(false, "虚拟机【" + server.getName() + "】创建快照失败");
						}
						List<Image> images = Lists.newArrayList();
						List<Snapshot> snaps = Lists.newArrayList();
						String content = JSONObject.toJSONString(result.getData());
						switch (provider) {
						case OPENSTACK:
							JSONObject jsonObject = JSONObject.parseObject(content);
							Object imgObj = jsonObject.get("image");
							if (null != imgObj) {
								ImageModel imgModel = JSONObject.parseObject(JSONObject.toJSONString(imgObj),
										ImageModel.class);
								Image image = new Image();
								BeanUtils.copyProperties(imgModel, image);
								image.setRemark(remark);
								image.setName(snapName);
								image.setVendorType(vendor.getType());
								image.preSave(userId, userId, vendor.getId(), server.getTenantId(),
										server.getProjectId());
								image.setCatalog("VM");
								imageRepository.save(image);
								images.add(image);
							}
							Object snapshotsObject = jsonObject.get("snapshots");
							if (null != snapshotsObject) {
								List<Snapshot> snapshots = snapshotRepository.listByVid(vendor.getId());
								Map<String, Snapshot> snapshotMap = Maps.newHashMap();
								for (Snapshot snapshot : snapshots) {
									snapshotMap.put(snapshot.getSnapshotUuid(), snapshot);
								}
								List<SnapshotModel> snapshotModels = JSONArray
										.parseArray(JSONObject.toJSONString(snapshotsObject), SnapshotModel.class);
								for (SnapshotModel snapshotModel : snapshotModels) {
									Volume volume = volumeRepository.getByVolumeUuid(snapshotModel.getVolumeUuid());
									if (snapshotMap.containsKey(snapshotModel.getSnapshotUuid())) {
										Snapshot oldSnapshot = snapshotMap.get(snapshotModel.getSnapshotUuid());
										BeanUtils.copyProperties(snapshotModel, oldSnapshot);
										oldSnapshot.setRemark(remark);
										oldSnapshot.setMenderId(userId);
										oldSnapshot.setVmId(serverId);
										if (null != volume) {
											oldSnapshot.setVolumeId(volume.getId());
										}
										// oldSnapshot.setProjectId(user.getProjectId());
										snapshotRepository.update(oldSnapshot);
									} else {
										Snapshot snapshot = new Snapshot();
										BeanUtils.copyProperties(snapshotModel, snapshot);
										snapshot.setRemark(remark);
										snapshot.preSave(userId, userId, vendor.getId(), serverId, server.getTenantId(),
												server.getProjectId());
										if (null != volume) {
											snapshot.setVolumeId(volume.getId());
										}
										snapshotRepository.save(snapshot);
										snaps.add(snapshot);
									}
								}
							}
							break;
						case VMWARE:
							Snapshot snapshot = JSONObject.parseObject(content, Snapshot.class);
							snapshot.preSave(userId, userId, server.getVendorId(), serverId, server.getTenantId(),
									server.getProjectId());
							if (null == snapshot.getSize()) {
								snapshot.setSize(0);
							}
							snapshot.setSnapshotType("VM");
							snapshot.setCatalog(context.getCatalog());
							snapshot.setParentId(getParentSnapshot(serverId));
							snapshotRepository.save(snapshot);
							snaps.add(snapshot);
							break;
						default:
							break;
						}
						if (null != server.getTenantId() && 0L != server.getTenantId()) {
							ObjectRelation vmRelation = objectRelationRepository.get(server.getId(),
									ResourceCategory.Computer.name());
							// 保存relation
							for (Snapshot snapshot : snaps) {
								// 保存资源关系信息
								ObjectRelation objectRelation = new ObjectRelation(context.getTarget(),
										snapshot.getId(), false, ResourceCategory.Snapshot.name(),
										context.getCatalog().name(), null);
								Integer snapSize = snapshot.getSize();
								if (null == snapSize) {
									snapSize = 0;
								}
								objectRelation.setSize(snapSize);
								// 同虚拟机的过期时间
								objectRelation.setExpiredTime(vmRelation.getExpiredTime());
								objectRelationRepository.save(objectRelation);
							}
							for (Image image : images) {
								// 保存资源关系信息
								ObjectRelation objectRelation = new ObjectRelation(context.getTarget(), image.getId(),
										false, ResourceCategory.Image.name(), context.getCatalog().name(), null);
								Double imageSize = image.getSize();
								if (null == imageSize) {
									imageSize = 0.0;
								}
								objectRelation.setSize(imageSize.intValue());
								// 同虚拟机的过期时间
								objectRelation.setExpiredTime(vmRelation.getExpiredTime());
								objectRelationRepository.save(objectRelation);
							}
						}
						ResourceEvent event = new ResourceEvent(serverId, "虚拟机挂载网卡", result.isSuccess() ? "成功" : "失败",
								context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
						resourceEventRepository.save(event);
						return new BocloudResult(true, "虚拟机【" + server.getName() + "】快照创建成功");
					}));
				}
				List<BocloudResult> succList = Lists.newArrayList();
				List<BocloudResult> failList = Lists.newArrayList();
				try {
					for (int i = 0; i < futures.size(); i++) {
						BocloudResult result = futures.get(i).get(30, TimeUnit.MINUTES);
						if (result.isSuccess()) {
							succList.add(result);
						} else {
							failList.add(result);
						}
					}
					// 创建成功的数量
					int success = succList.size();
					// 创建失败的数量
					int fail = failList.size();
					// 发送站内信
					String content = null;
					if (fail == serverIds.size()) {
						content = "虚拟机快照创建失败，详情如下：\n";
						for (BocloudResult bocloudResult : failList) {
							if(!content.contains(bocloudResult.getMessage())) {
								content += bocloudResult.getMessage() + "\n";
							}
						}
					} else {
						content = "虚拟机快照创建成功【" + success + "】个,失败【" + fail + "】个，详情如下：\n";
						for (BocloudResult bocloudResult : succList) {
							content += bocloudResult.getMessage() + "\n";
						}
						for (BocloudResult bocloudResult : failList) {
							if(!content.contains(bocloudResult.getMessage())) {
								content += bocloudResult.getMessage() + "\n";
							}
						}
					}
					resourceEventPublisher.send(new OperateResult(fail == 0, content, operate,
							MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
				} catch (Exception e) {
					logger.error("Get error message：", e);
					resourceEventPublisher.send(new OperateResult(false, "虚拟机批量快照失败", operate,
							MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
				}
			}).start();
			return new BocloudResult(true, "虚拟机快照批量创建任务已下发，请等待执行结果...");
		} catch (Exception e) {
			logger.error("Get error message：", e);
			return new BocloudResult(false, "虚拟机批量快照失败");
		}
	}

	private BocloudResult<ChargeResultTrend> getNumberTrend(RequestContext context) {
		List<String> timeList = timeToList(new JSONObject(MapTools.simpleMap("time", DateUtils.Time.MONTHS.getName())));
		List<String> keys = new ArrayList<>(timeList);
		List<ChargeTrendData> values = new ArrayList<>();
		ArrayList<Object> total = new ArrayList<>();
		try {
			List<CloudServer> cloudServerList = getServerList(context,true);
			for (String time : timeList) {
				// 筛选目标虚机 在 指定时间前创建 指定条件主机下 非创建中的虚机
				List<CloudServer> targetVms = cloudServerList.stream().filter(
					cloudServer -> !BocloudStatus.Server.BUILDING.name().equals(cloudServer.getStatus()) && cloudServer
						.getGmtCreate()
						.after(DateUtils.stringToDate(time.substring(0, 10) + " 00:00:00", "yyyy-MM-dd HH:mm:ss"))
						&& cloudServer.getGmtCreate()
						.before(DateUtils.stringToDate(time.substring(0, 10) + " 23:59:59", "yyyy-MM-dd HH:mm:ss")))
					.collect(Collectors.toList());
				total.add(targetVms.size());

			}
			ChargeTrendData chargeTrendData = new ChargeTrendData("数量", total);
			values.add(chargeTrendData);
			return new BocloudResult<>(true, new ChargeResultTrend(keys, values), "查询成功");
		} catch (Exception e) {
			logger.error("get cloude server number trend error", e);
			return new BocloudResult<>(false, null, "查询失败");
		}
	}

	private BocloudResult<JSONArray> getStatusStatistics(RequestContext context) {
		try {
			JSONArray result = new JSONArray();
			List<CloudServer> userServerList = getServerList(context,false);
			Map<String, List<CloudServer>> serverMap = userServerList.stream()
					.collect(groupingBy(CloudServer::getStatus));
			HashMap<String, List<CloudServer>> resultMap = new HashMap<>();
			for (Map.Entry<String, List<CloudServer>> serverEntry : serverMap.entrySet()) {
				String key;
				if (serverEntry.getKey().equals(BocloudStatus.Server.RUNNING.name())
						|| serverEntry.getKey().equals(BocloudStatus.Basic.ENABLED.name())) {
					key = "开机";
				} else if (serverEntry.getKey().equals(BocloudStatus.Server.STOPPED.name())) {
					key = "关机";
				} else if (serverEntry.getKey().equals(BocloudStatus.Server.ERROR.name())) {
					key = "断开";
				} else if (serverEntry.getKey().equals(BocloudStatus.Server.EXCEPTION.name())) {
					key = "异常";
				} else if (serverEntry.getKey().equals(BocloudStatus.Server.PAUSED.name())) {
					key = "暂停";
				} else if (serverEntry.getKey().equals(BocloudStatus.Server.SUSPENDED.name())) {
					key = "挂起";
				} else {
					key = "其他";
				}
				List<CloudServer> serverList = Optional.ofNullable(serverEntry.getValue()).orElse(new ArrayList<>());
				if (resultMap.containsKey(key)) {
					List<CloudServer> list = resultMap.get(key);
					list.addAll(serverList);
					resultMap.put(key, list);
				} else {
					resultMap.put(key, serverList);
				}
			}
			for (Map.Entry<String, List<CloudServer>> entry : resultMap.entrySet()) {
				JSONObject jsonObject = new JSONObject();
				jsonObject.put("name", entry.getKey());
				jsonObject.put("value", entry.getValue().size());
				result.add(jsonObject);
			}
			return new BocloudResult<>(true, result, "查询成功");
		} catch (Exception e) {
			logger.error("get cloud server number count error,", e);
			return new BocloudResult<>(false, "查询失败:" + e.getMessage());
		}
	}

	private List<CloudServer> getServerList(RequestContext context,Boolean containRemove) {
		if (context.getCatalog().equals(Catalog.Tenant)) {
			// 租户能看到 1.属于当前租户的资源 2.租户下所有项目的资源
			List<Project> tenantProjects = smsProjectService.listTenantProjects(context.getTenant());
			List<Long> projectIds = tenantProjects.stream().map(Project::getId).collect(Collectors.toList());
			return this.cloudServerRepository.listAll(1, Integer.MAX_VALUE, null, context.getTenant(), projectIds, null,
					null,containRemove);
		} else if (context.getCatalog().equals(Catalog.User)) {
			// 用户能看到 1.自己申请的资源 2.自己所在的资源可见项目（资源对项目下所有成员可见）下创建的资源 3.自己管理的项目下的资源
			List<Project> userManagerProjects = smsProjectService.listUserManagerProjects(context.getTarget());
			List<Project> visibleProjects = smsProjectService.listUserVisibleProjects(context.getTarget());
			List<Long> projectIds = new ArrayList<>();
			List<Long> userManagerProjectsIds = userManagerProjects.stream().map(Project::getId)
					.collect(Collectors.toList());
			if (!userManagerProjectsIds.isEmpty()) {
				projectIds.addAll(userManagerProjectsIds);
			}
			List<Long> visibleProjectsIds = visibleProjects.stream().map(Project::getId).collect(Collectors.toList());
			if (!visibleProjectsIds.isEmpty()) {
				projectIds.addAll(visibleProjectsIds);
			}
			return this.cloudServerRepository.listAll(1, Integer.MAX_VALUE, context.getTarget(), null, projectIds, null,
					null,containRemove);
		}
		return Lists.newArrayList();
	}

	@Override
	public BocloudResult count(Long userId, Long projectId, Long tenantId) {
		Catalog catalog = Catalog.Tenant;
		Long target = tenantId;
		if (null != userId) {
			target = userId;
			catalog = Catalog.User;
		}
		List<Project> projects = smsProjectService.projectsByCondition(target, catalog);
		List<Long> projectIds = new ArrayList<>();
		// 此时查询的是全部用户全部项目的信息
		if (null != projectId && 0L != projectId) {
			projectIds.add(projectId);
		} else if (!ListTool.isEmpty(projects)) {
			projects.forEach(project -> projectIds.add(project.getId()));
		} else {
			// 当前用户不属于任何项目，则登录之后查看不到任何虚拟机信息
			projectIds.add(-1L);
		}
		try {
			int total = this.cloudServerRepository.count(Lists.newArrayList(), null, null, projectIds, null);
			return new BocloudResult(true, total, "查询成功");
		} catch (Exception e) {
			logger.error("Get error message：", e);
			return new BocloudResult(false, "查询失败");
		}
	}

	@Override
	public BocloudResult<List<CloudServer>> listTemplate(Long vendorId, Long vdcId) {
		try {
			List<CloudServer> servers = cloudServerRepository.listTemplate(vendorId, vdcId);
			return new BocloudResult(true, servers, "查询成功");
		} catch (Exception e) {
			logger.error("Get error message：", e);
			return new BocloudResult(false, "查询失败");
		}
	}

	/**
	 * 取消定时快照任务
	 *
	 * @param serverId
	 * @param context
	 * @return
	 */
	@Override
	public BocloudResult cancelSnapshotTask(Long serverId, RequestContext context) {
		try {
			snapshotTaskService.removeByVmId(serverId);
			return new BocloudResult(true, "定时快照任务取消成功");
		} catch (Exception e) {
			logger.error("Get error message：", e);
			return new BocloudResult(false, "定时快照任务取消失败");
		}
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		serverDelayCreateQueue = new LinkedBlockingQueue<>();
		new Thread(new CloudServerCreateTask(serverDelayCreateQueue, this)).start();
	}

	@Override
	public BocloudResult operations(Long id, VmGenericParam vmGenericParam, RequestContext context) {
		if (null == vmGenericParam) {
			return new BocloudResult(false, "无效操作！");
		}
		String action = vmGenericParam.getAction();
		// 克隆
		if ("clone".equalsIgnoreCase(action)) {
			return this.clone(vmGenericParam, context);
		}
		// 迁移虚拟机
		if ("migrate".equalsIgnoreCase(action)) {
			return this.migrate(vmGenericParam, context);
		}
		// 迁移OpenStack虚拟机
		if ("OSMigrate".equalsIgnoreCase(action)) {
			return this.osMigrate(vmGenericParam, context);
		}
		if ("start".equalsIgnoreCase(action)) {
			return this.start(id, context);
		}
		if ("stop".equalsIgnoreCase(action)) {
			return this.stop(id, context);
		}
		if ("restart".equalsIgnoreCase(action)) {
			return this.restart(id, context);
		}
		if ("softrestart".equalsIgnoreCase(action)) {
			return this.softRestart(id, context);
		}
		// 暂停
		if ("pause".equalsIgnoreCase(action)) {
			return this.pause(id, context);
		}
		// 恢复
		if ("recovery".equalsIgnoreCase(action)) {
			return this.recovery(id, context);
		}
		// 挂起
		if ("suspend".equalsIgnoreCase(action)) {
			return this.suspend(id, context);
		}
		// 恢复虚拟机(openstack睡眠状态)
		if ("resume".equalsIgnoreCase(action)) {
			return this.resume(id, context);
		}
		// 激活
		if ("active".equalsIgnoreCase(action)) {
			return this.active(id, context);
		}
		// 备份
		if ("backup".equalsIgnoreCase(action)) {
			return this.backup(id, context);
		}
		// 虚拟机进入回收站
		if ("recycle".equalsIgnoreCase(action)) {
			return vmApplyService.recycle(vmGenericParam.getId(), context);
		}
		// 虚拟机回收站还原
		if ("restore".equalsIgnoreCase(action)) {
			return vmApplyService.restore(id, context);
		}
		// 重置虚拟机状态
		if ("resetStatus".equalsIgnoreCase(action)) {
			return vmExtendService.resetStatus(id, context);
		}
		// 取消定时快照任务
		if ("cancelSnapshotTask".equalsIgnoreCase(action)) {
			return this.cancelSnapshotTask(id, context);
		}
		if ("setMaxBandwidth".equalsIgnoreCase(action)) {
			return vmExtendService.setMaxBandwidth(vmGenericParam, context);
		}
		if ("resetInstance".equalsIgnoreCase(action)) {
			return vmExtendService.resetInstance(JSON.toJSONString(vmGenericParam), context);
		}
		if ("attachNics".equalsIgnoreCase(action)) {
			// return this.secondBindNics(id, params, context);
		}
		if ("detachNics".equalsIgnoreCase(action)) {
			// return this.secondUnBindNics(id, params, context);
		}
		if ("cloneAsTemplate".equals(action)) {
			return this.cloneAsTemplate(vmGenericParam, context);
		}
		if ("deallocate".equals(action)) {
			return this.deallocate(id, context);
		}
		if ("recycleByUuid".equals(action)) {
			return vmApplyService.recycle(vmGenericParam.getUuid(), context);
		}
		if ("enableTermination".equals(action)) {
			return this.switchTermination(id, context, true);
		}
		if ("disableTermination".equals(action)) {
			return this.switchTermination(id, context, false);
		}
		return new BocloudResult(false, "无效操作！");
	}

	@Override
	public BocloudResult batchOperations(VmBatchOperationParam batchOperationParam, RequestContext context) {
		if (null == batchOperationParam || StringUtils.isEmpty(batchOperationParam.getAction())) {
			return new BocloudResult(false, "无效操作！");
		}
		String action = batchOperationParam.getAction();
		if ("Reboot".equalsIgnoreCase(action)) {
			return this.batchReboot(batchOperationParam.getIds(), context);
		} else if ("Start".equalsIgnoreCase(action)) {
			return this.batchStart(batchOperationParam.getIds(), context);
		} else if ("Stop".equalsIgnoreCase(action)) {
			return this.batchStop(batchOperationParam.getIds(), context);
		} else if ("Clones".equalsIgnoreCase(action)) {
			return this.batchClone(JSON.toJSONString(batchOperationParam), context);
		} else if ("resetInstance".equalsIgnoreCase(action)) {
			return vmExtendService.resetInstance(JSON.toJSONString(batchOperationParam), context);
		} else if ("removeByInstanceIds".equalsIgnoreCase(action)) {
			return vmExtendService.removeByInstanceIds(JSON.toJSONString(batchOperationParam), context);
		} else if ("recycle".equalsIgnoreCase(action)) {
			return vmApplyService.batchRecycle(JSON.toJSONString(batchOperationParam), context);
		}
		return new BocloudResult(false, "无效操作！");
	}

	@Override
	public BocloudResult details(Long id, RequestContext context, String action, String params) {
		if ("realtime".equalsIgnoreCase(action)) {
			return vmExtendService.detailInRealTime(id);
		}
		return this.detail(id);
	}

	public BocloudResult switchTermination(Long serverId, RequestContext context, Boolean enabled) {
		String path = CloudServer.class.getSimpleName() + "_" + serverId;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			CloudServer server = cloudServerRepository.get(serverId);
			Assert.notNull(server, "虚拟机不存在");
			CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
			Assert.notNull(vendor, "云平台不存在");
			BocloudResult result = serverDriver.disableApiTermination(vendor.getUuid(), server.getRegionId(),
					server.getInstanceId(), enabled);
			if (result.isSuccess()) {
				server.setGmtModify(new Date());
				server.setTerminationProtected(enabled);
				server.setMenderId(context.getTarget());
				cloudServerRepository.update(server);
				return new BocloudResult(true, enabled ? "启动终止保护成功" : "禁用终止保护成功");
			}
			return result;
		} catch (Exception e) {
			logger.error("enable termination protected fail:", e);
			return new BocloudResult(false, "修改终止保护状态失败");
		}
	}

	@Override
	public BocloudResult condition(Integer page, Integer rows, String condition, RequestContext context) {
		condition = Optional.ofNullable(condition).orElse("");
		JSONObject object = JSONObject.parseObject(condition);
		String action = object.getString("condition");
		// 判断是否存在
		if ("exists".equalsIgnoreCase(action)) {
			String name = object.getString("name");
			Long vendorId = object.getLong(Common.VENDORID);
			return this.exists(name, vendorId);
		} else if ("count".equalsIgnoreCase(action)) {
			// 汇总虚拟机数量
			Long tenantId = object.getLong("tenantId");
			return this.count(context.getTarget(), object.getLong("projectId"), tenantId);
		} else if ("hasAuth".equalsIgnoreCase(action)) {
			// 查询虚拟机是否具有认证信息
			Long serverId = object.getLong("serverId");
			return vmExtendService.queryAccount(serverId);
		} else if ("Keypair".equalsIgnoreCase(action)) {
			// 根据秘钥查询已绑定的虚拟机列表
			return vmExtendService.listServerByKeypair(object, context);
		} else if ("image".equalsIgnoreCase(action)) {
			// 按照ImageUuid查询虚拟机
			String imageUuid = object.getString("imageUuid");
			return vmExtendService.listByImageUuid(imageUuid);
		} else if ("host".equalsIgnoreCase(action)) {
			// 根据host
			Long hostId = object.getLong("hostId");
			return vmExtendService.listByHostId(hostId);
		} else if ("network".equalsIgnoreCase(action)) {
			// 根据网络查询
			Long networkId = object.getLong("networkId");
			return vmExtendService.listByNetworkId(networkId);
		} else if ("uuid".equalsIgnoreCase(action)) {
			// 根据uuid
			String uuid = object.getString("uuid");
			return vmExtendService.queryByUuid(uuid);
		} else if ("serverFault".equalsIgnoreCase(action)) {
			try {
				// 虚拟机
				CloudServer server = cloudServerRepository.query(object.getLong(Common.ID));
				Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
				CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
				Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
				return serverDriver.detailFault(server.getInstanceId(), vendor.getUuid(), null);
			} catch (Exception e) {
				logger.error("Get error message:{}", e);
				return new BocloudResult(false, "查询失败");
			}
		} else if ("listByCondition".equalsIgnoreCase(action)) {
			List<CloudServer> servers = cloudServerRepository.listByCondition(object.getLong("vendorId"),
					object.getLong("vdcId"), object.getLong("clusterId"));
			return new BocloudResult(true, servers, "查询成功");
		} else if ("listByVms".equalsIgnoreCase(action)) {
			List<CloudServer> servers = cloudServerRepository
					.listByVms(object.getJSONArray("serverIds").toJavaList(Long.class));
			return new BocloudResult(true, servers, "查询成功");
		} else if ("listTenantProject".equalsIgnoreCase(action)) {
			Boolean isAll = object.getBoolean("isAll");
			List<Long> tenantIds = JSON.parseArray(object.getString("tenantIds"), Long.class);
			List<Long> projectIds = JSON.parseArray(object.getString("projectIds"), Long.class);
			List<CloudServer> servers = cloudServerRepository.listVmsByTenants(tenantIds, isAll, projectIds);
			return new BocloudResult(true, servers, "查询成功");
		} else if ("basic".equalsIgnoreCase(action)) {
			return this.basic(object.getLong("serverId"));
		} else if ("AvailableVm".equalsIgnoreCase(action)) {
			return listAvailableVm(object.getLong("vendorId"), object.getString("regionId"), context);
		} else if ("hicUnBindEip".equalsIgnoreCase(action)) {// 华为云，未绑定弹性公网IP的虚拟机
			return hicUnBindEip(object, context);
		} else if ("poolgroup".equalsIgnoreCase(action)) { // 汇总虚拟机数量
			return vmExtendService.listByPoolGroupId(page, rows, condition, context);
		} else if ("getStatusStatistics".equalsIgnoreCase(action)) {
			// 获取云主机状态概览
			return this.getStatusStatistics(context);
		} else if ("getNumberTrend".equalsIgnoreCase(action)) {
			// 获取云主机数量趋势
			return this.getNumberTrend(context);
		} else if ("listBySlb".equalsIgnoreCase(action)) {
			return this.listBySlb(object, context);
		}
		return new BocloudResult<>(false, "参数格式错误");
	}

	private BocloudResult hicUnBindEip(JSONObject object, RequestContext context) {
		try {
			Long vendorId = object.getLong(Common.VENDORID);
			String regionId = object.getString(Common.REGIONID);
			List<Long> vmIds = new ArrayList<>();
			if (context.getCatalog().equals(Catalog.Tenant) || context.getCatalog().equals(Catalog.User)) {
				List<Param> params = new ArrayList<Param>();
				params.add(new Param(MapTools.simpleMap("vendorId", vendorId), Sign.EQ));
				params.add(new Param(MapTools.simpleMap("regionId", regionId), Sign.EQ));
				Pager pager = new Pager(1, 100, params, null);
				BocloudResult<GridBean<CloudServer>> vmListResult = this.list(pager, context);
				if (vmListResult.isFailed()) {
					return vmListResult;
				}
				List<CloudServer> list = vmListResult.getData().getRows();
				if (!ListTool.isEmpty(list)) {
					vmIds = list.stream().map(CloudServer::getId).collect(Collectors.toList());
				}
			}
			List<CloudServer> servers = cloudServerRepository.listHicUnBindEip(vendorId, regionId, vmIds);
			return new BocloudResult(true, servers, "查询成功");
		} catch (Exception e) {
			logger.error("查询实例列表异常：" + e.getMessage());
			return new BocloudResult<>(false, "查询实例列表异常：" + e.getMessage());
		}
	}

	private BocloudResult listBySlb(JSONObject object, RequestContext context) {
		try {
			Long poolId = object.getLong("poolId");
			LbPool lbPool = lbPoolRepository.query(poolId);
			if (null == lbPool) {
				return new BocloudResult<>(false, "服务器组不存在");
			}
			LoadBalancer loadBalancer = loadBalancerRepository.queryByUuid(lbPool.getLbUuid(), lbPool.getVendorId());
			if (null == loadBalancer) {
				return new BocloudResult<>(false, "负载均衡数据不存在");
			}
			String vpcUuid = loadBalancer.getVpcUuid();
			if (StringUtils.isEmpty(vpcUuid)) {
				return new BocloudResult<>(false, "网络信息异常，请同步后在进行此操作");
			}
			List<CloudServer> cloudServers = cloudServerRepository.listByVendorId(loadBalancer.getVendorId(),
					loadBalancer.getRegion());
			if (ListTool.isEmpty(cloudServers)) {
				return new BocloudResult<>(true, cloudServers, "查询成功！");
			}
			Set<CloudServer> resultList = new HashSet<>();
			for (CloudServer cloudServer : cloudServers) {
				List<JSONObject> parseArray = JSONObject.parseArray(cloudServer.getPrivateIps(), JSONObject.class);
				if (ListTool.isEmpty(parseArray)) {
					continue;
				}
				for (JSONObject netObject : parseArray) {
					if (vpcUuid.equalsIgnoreCase(netObject.getString("networkId"))) {
						resultList.add(cloudServer);
					}
				}
			}
			return new BocloudResult<>(true, resultList, "查询成功");
		} catch (Exception e) {
			logger.info("查询可用负载成员异常：" + e.getMessage());
			return new BocloudResult<>(false, "查询失败 ：" + e.getMessage());
		}
	}

	@Override
	public BocloudResult listAvailableVm(Long vendorId, String regionId, RequestContext context) {
		try {
			List<CloudServer> listAvailableVm = new ArrayList<>();
			if (context.getCatalog().equals(Catalog.Tenant)) {
				// 租户能看到 1.属于当前租户的资源 2.租户下所有项目的资源
				List<Project> tenantProjects = smsProjectService.listTenantProjects(context.getTenant());
				List<Long> projectIds = tenantProjects.stream().map(Project::getId).collect(Collectors.toList());
				listAvailableVm = cloudServerRepository.listAvailableVm(vendorId, regionId, null, context.getTenant(),
						projectIds);
			} else if (context.getCatalog().equals(Catalog.User)) {
				// 用户能看到 1.自己申请的资源 2.自己所在的资源可见项目（资源对项目下所有成员可见）下创建的资源 3.自己管理的项目下的资源
				List<Project> userManagerProjects = smsProjectService.listUserManagerProjects(context.getTarget());
				List<Project> visibleProjects = smsProjectService.listUserVisibleProjects(context.getTarget());
				List<Long> projectIds = new ArrayList<>();
				List<Long> userManagerProjectsIds = userManagerProjects.stream().map(Project::getId)
						.collect(Collectors.toList());
				if (!userManagerProjectsIds.isEmpty()) {
					projectIds.addAll(userManagerProjectsIds);
				}
				List<Long> visibleProjectsIds = visibleProjects.stream().map(Project::getId)
						.collect(Collectors.toList());
				if (!visibleProjectsIds.isEmpty()) {
					projectIds.addAll(visibleProjectsIds);
				}
				listAvailableVm = cloudServerRepository.listAvailableVm(vendorId, regionId, context.getTarget(), null,
						projectIds);
			} else {
				listAvailableVm = cloudServerRepository.listAvailableVm(vendorId, regionId);
			}
			return new BocloudResult(true, listAvailableVm, "查询成功");
		} catch (Exception e) {
			logger.error("Get error message:{}", e);
			return new BocloudResult(false, "查询失败");
		}
	}

	@Override
	public BocloudResult getBusinessById(Long id) {
		try {
			CloudServer server = cloudServerRepository.get(id);
			if (null == server) {
				return new BocloudResult(true, null, "虚拟机映射关系查询成功");
			}
			CloudServerBusiness serverBusiness = serverBusinessRepository.getByServerId(server.getId());
			return new BocloudResult(true, serverBusiness, "虚拟机映射关系查询成功");
		} catch (Exception e) {
			logger.error("虚拟机映射关系查询失败：" + e);
			return new BocloudResult(false, "虚拟机映射关系查询失败");
		}
	}

	@Override
	public BocloudResult configSeq(String params, RequestContext context) {
		try {
			CloudServerBusiness business = JSONObject.parseObject(params, CloudServerBusiness.class);
			CloudServerBusiness bean = serverBusinessRepository.getByServerId(business.getServerId());
			if (null == bean) {
				business.setCreatorId(context.getTarget());
				business.setGmtCreate(new Date());
				serverBusinessRepository.save(business);
			} else {
				BeanUtils.copyProperties(business, bean);
				bean.setDeleted(false);
				business.setMenderId(context.getTarget());
				business.setGmtModify(new Date());
				serverBusinessRepository.update(bean);
			}
			return new BocloudResult(true, "流水号配置成功");
		} catch (Exception e) {
			logger.error("Get error message:{}", e);
			return new BocloudResult(false, "流水号配置失败");
		}
	}

}
