package com.bocloud.ims.service.resource;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.common.BillingDriver;
import com.bocloud.cmp.driver.compute.ServerDriver;
import com.bocloud.cmp.driver.compute.ServerTemplateDriver;
import com.bocloud.cmp.driver.compute.SnapshotDriver;
import com.bocloud.cmp.driver.network.ElasticIpDriver;
import com.bocloud.cmp.entity.enums.*;
import com.bocloud.cmp.model.*;
import com.bocloud.cmp.model.common.*;
import com.bocloud.cmp.model.fusionsphere.CdromModel;
import com.bocloud.cmp.model.sangfor.SangforConModel;
import com.bocloud.cmp.model.sangfor.SangforNetwork;
import com.bocloud.cmp.model.sangfor.SangforServerModel;
import com.bocloud.cmp.model.sangfor.SangforSnapshotModel;
import com.bocloud.cmp.vm.model.*;
import com.bocloud.common.encrypt.AESEncrptor;
import com.bocloud.common.encrypt.Encryptor;
import com.bocloud.common.enums.ResourceCatalog;
import com.bocloud.common.model.*;
import com.bocloud.common.model.OperateResult.OperateCategory;
import com.bocloud.common.model.RequestContext.Catalog;
import com.bocloud.common.utils.*;
import com.bocloud.cos.enums.VendorType;
import com.bocloud.entity.bean.GenericEntity;
import com.bocloud.ims.common.enums.ServerAction;
import com.bocloud.ims.common.utils.FastjsonUtils;
import com.bocloud.ims.entity.common.Dictionary;
import com.bocloud.ims.entity.common.*;
import com.bocloud.ims.entity.params.SkuParams;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.ResourceQuota.Action;
import com.bocloud.ims.entity.resource.hmc.HmcPartition;
import com.bocloud.ims.interfaces.resource.*;
import com.bocloud.ims.interfaces.resource.hmc.HmcPartitionService;
import com.bocloud.ims.interfaces.resource.sangfor.SangforAzService;
import com.bocloud.ims.interfaces.scheduler.SnapshotTaskService;
import com.bocloud.ims.repository.resource.*;
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.common.ShtermService;
import com.bocloud.ims.service.internal.*;
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.model.excel.ImportCloudServerTemplate;
import com.bocloud.ims.service.task.ResourceTaskNotice;
import com.bocloud.ims.service.thread.CloudServerCreateTask;
import com.bocloud.ims.service.thread.CloudServerParam;
import com.bocloud.ims.service.transporter.vendor.DataUtil;
import com.bocloud.ims.service.transporter.vendor.SangforV68Transporter;
import com.bocloud.ims.service.transporter.vendor.SmartxTransporter;
import com.bocloud.ims.service.utils.*;
import com.bocloud.nms.enums.ChargeCommon;
import com.bocloud.nms.enums.OrderItemStatus;
import com.bocloud.rpc.interfaces.sms.SmsRpcService;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.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.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

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

/**
 * 云主机实现类
 *
 * @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.HCSO.name(), CloudProvider.TENCENT.name(),
            CloudProvider.JDCLOUD.name(), CloudProvider.ALIYUN.name(), CloudProvider.AWS.name(),
            CloudProvider.TENCENT.name(), CloudProvider.TCE.name(), CloudProvider.AZURE.name()};

    private static final Integer LICENSE_NODE_COUONT = 10;
    @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 ServerTemplateDriver serverTemplateDriver;
    @Autowired
    private SnapshotDriver snapshotDriver;
    @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 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 LvmService lvmService;
    @Autowired
    private SmsUserService smsUserService;
    @Autowired
    private SmsBusinessService smsBusinessService;
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private ElasticIpService elasticIpService;
    @Autowired
    private LicenseSerivce licenseSerivce;
    @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 CosInternalService cosInternalService;
    @Autowired
    private SmartxTransporter smartTransporter;
    @Autowired
    private ElasticIpDriver elasticIpDriver;
    @Autowired
    private ResourceTaskNotice resourceTaskNotice;
    @Autowired
    private SangforServerGroupRepository serverGroupRepository;
    @Autowired
    private BillingDriver billingDriver;
    @Autowired
    private SangforAzService sangforAzService;
    @Autowired
    private SmsSystemConfigService smsSystemConfigService;
    @Autowired
    private ShtermService shtermService;

    @Autowired
    private IpService ipService;
    @Autowired
    SmsRpcService smsRpcService;
    @Autowired
    ResourceAllocateServiceImpl resourceAllocateServiceImpl;

    @Override
    public BocloudResult<GridBean<CloudServer>> list(Pager pager, RequestContext context) {
        GridBean<CloudServer> gridBean;
        try {
            List<Param> params = Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>());
            Boolean simple = Optional.ofNullable(pager.getSimple()).orElse(false);

            Map<String, String> sorter = Optional.ofNullable(pager.getSorter()).orElse(Maps.newLinkedHashMap());
            if (sorter.getClass().equals(HashMap.class)) {
                sorter = new LinkedHashMap<>(sorter);
                pager.setSorter(sorter);
            }
            sorter.put("azUuid", Common.ZERO);
            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;
            List<CloudServer> list = Lists.newArrayList();
            // 自服务侧查询未分配虚拟机
            boolean isAssign = true;
            Long vendorId = null;
            for (int i = 0; i < params.size(); i++) {
                Map<String, Object> param = params.get(i).getParam();
                if (param.get("isAssign") != null) {
                    if (null != param.get("vendorId")) {
                        vendorId = Long.valueOf(param.get("vendorId").toString());
                    }
                    param.remove("isAssign");
                    param.remove("vendorId");
                    params.get(i).setParam(param);
                    isAssign = false;
                }
            }
            if (!isAssign) {
                if (null != vendorId) {
                    total = cloudServerRepository.getNoTenantCount(vendorId, page, rows, params);
                    list = cloudServerRepository.getNoTenantList(vendorId, page, rows, params);
                    gridBean = new GridBean<>(page, rows, total, list);
                    return new BocloudResult<>(true, gridBean, "查询成功");
                } else {
                    total = cloudServerRepository.getNoTenantCountNoVendor(vendorId, page, rows, params);
                    list = cloudServerRepository.getNoTenantListNoVendor(vendorId, page, rows, params);
                    gridBean = new GridBean<>(page, rows, total, list);
                    return new BocloudResult<>(true, gridBean, "查询成功");
                }
            }
            if (context.getCatalog().equals(Catalog.Tenant)) {
                if (simple) {
                    rows = Integer.MAX_VALUE;
                }
                // 租户能看到 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)) {
                if (simple) {
                    rows = Integer.MAX_VALUE;
                }
                // 用户能看到 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) {
                Map<String, String> allAzUuidNameMap = sangforAzService.getAllAzUuidNameMap();

                Set<Long> tenantIds = new HashSet<>();
                Set<Long> userIds = new HashSet<>();
                Set<Long> businessIds = new HashSet<>();
                Set<Long> projectIds = new HashSet<>();
                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 = new HashMap<>();
                Map<Long, String> projectMap = new HashMap<>();
                Map<Long, String> businessMap = new HashMap<>();
                Map<Long, String> tenantMap = new HashMap<>();

                if (!userIds.isEmpty()) {
                    userMap = smsUserService.listUsersByIds(new ArrayList<>(userIds)).stream()
                            .collect(Collectors.toMap(User::getId, User::getName));
                }
                if (!projectIds.isEmpty()) {
                    projectMap = smsProjectService.listProjectsByIds(new ArrayList<>(projectIds)).stream()
                            .collect(Collectors.toMap(Project::getId, Project::getName));
                }
                if (!businessIds.isEmpty()) {
                    businessMap = smsBusinessService.listBusinesssByIds(new ArrayList<>(businessIds)).stream()
                            .collect(Collectors.toMap(Business::getId, Business::getName));
                }
                if (!tenantIds.isEmpty()) {
                    tenantMap = smsTenantService.listTenantsByIds(new ArrayList<>(tenantIds)).stream()
                            .collect(Collectors.toMap(Tenant::getId, Tenant::getName));
                }

                Map<Long, List<CloudServer>> vendorIdMapServer = list.stream().collect(groupingBy(CloudServer::getVendorId));
                //select a.* from volume a where a.is_deleted = 0 and a.server_id = :serverId and a.name in ('Hard disk 1','硬盘 1')
                //根据云平台分组然后查询对应平台的云硬盘
                Map<Long, Integer> serverIdMapSysSize = new HashMap<>();
                vendorIdMapServer.forEach((vid, vms)->{
                    List<Long> serverIdList = vms.stream().map(CloudServer::getId).collect(Collectors.toList());
                    List<Volume> sysVolumes = volumeRepository.queryProxy()
                            .col(Volume::getVendorId).eq(vid)
                            .col("server_id").in(serverIdList).col("name").in("Hard disk 1", "硬盘 1").col("is_deleted").eq(0)
                            .list();
                    sysVolumes.forEach(volume -> {
                        serverIdMapSysSize.put(volume.getServerId(), volume.getSize());
                    });
                });
                String azUuid, azName;
                for (CloudServer server : list) {
                    azUuid = server.getAzUuid();
                    if (StringUtils.isNotEmpty(azUuid)) {
                        azName = allAzUuidNameMap.get(azUuid);
                        if (StringUtils.isNotEmpty(azName)) {
                            server.setAzName(azName);
                        }
                    }

                    // 设置云主机归属信息
                    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.EASYSTACK == 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) {
                        server.setSystemDiskSize(serverIdMapSysSize.get(server.getId()));
                    }
                    if (CloudProvider.TIANYI == provider || CloudProvider.HUAWEI == provider
                            || CloudProvider.HCSO == 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());
                        }
                    }
                    //Azure
                    if (CloudProvider.AZURE == provider) {
                        Optional.ofNullable(resourceGroupRepository.query(server.getResourceGroupId())).map(ResourceGroup::getName).ifPresent(server::setResourceGroupName);
                    }
                }
                gridBean.setRows(list);
            }
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("Query vm list fail", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult<GridBean<CloudServer>> countByUser(Pager pager, RequestContext context) {
        GridBean<CloudServer> gridBean;
        try {
            List<Param> params = Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>());
            Boolean simple = Optional.ofNullable(pager.getSimple()).orElse(false);

            Map<String, String> sorter = Optional.ofNullable(pager.getSorter()).orElse(Maps.newLinkedHashMap());
            if (sorter.getClass().equals(HashMap.class)) {
                sorter = new LinkedHashMap<>(sorter);
                pager.setSorter(sorter);
            }
            sorter.put("azUuid", Common.ZERO);
            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;
            List<CloudServer> list = Lists.newArrayList();
            if (context.getCatalog().equals(Catalog.Tenant)) {
                if (simple) {
                    rows = Integer.MAX_VALUE;
                }
                // 租户能看到 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);
                gridBean = new GridBean<>(page, rows, total, list);
            } else if (context.getCatalog().equals(Catalog.User)) {
                if (simple) {
                    rows = Integer.MAX_VALUE;
                }
                // 用户能看到 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);
                gridBean = new GridBean<>(page, rows, total, list);
            } else {
                // 管理端搜索
                if (null != clusterId) {
                    total = this.cloudServerRepository.count(clusterId, params);
                    gridBean = new GridBean<>(page, rows, total, list);
                } else {
                    total = this.cloudServerRepository.vmCount(params, labelContent);
                    gridBean = new GridBean<>(page, rows, total, list);
                }
            }
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("Query vm list fail", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public void importData(MultipartFile multipartFile, RequestContext requestContext) throws IOException {
        String originalFilename = multipartFile.getOriginalFilename();
        Assert.notNull(originalFilename, "文件名不能为空");
        ImportExcelListener<ImportCloudServerTemplate> importExcelListener = new ImportExcelListener<>();
        EasyExcel.read(multipartFile.getInputStream(), ImportCloudServerTemplate.class, importExcelListener).excelType(ExcelTypeEnum.XLSX).sheet().doRead();
        List<ImportCloudServerTemplate> importCloudServerTemplates = importExcelListener.getList();
        batchInsert(importCloudServerTemplates, requestContext);
    }

    @Override
    public void sendNotice(boolean b, String s, RequestContext requestContext) {
        resourceEventPublisher.send(new OperateResult(b, s, "", MapTools.simpleMap(Common.VENDORID, 0),
                OperateResult.OperateCategory.ResourceEvent, requestContext));
    }

    private void batchInsert(List<ImportCloudServerTemplate> importCloudServerTemplates, RequestContext requestContext) {
        Integer successNum = 0;
        Integer errorNumber = 0;
        //错误信息
        // ip为null的错误信息
        StringBuilder ipNullMsg = new StringBuilder();
        // 负责人为null的错误信息
        StringBuilder managerNullMsg = new StringBuilder();
        // 负责人不属于租户的错误信息
        StringBuilder notTenantOfUserMsg = new StringBuilder();
        // 当前资源在租户下但回收失败的错误信息
        StringBuilder reclaimFaileMsg = new StringBuilder();
        // 分配失败的错误信息
        StringBuilder assignFaileMsg = new StringBuilder();

        StringBuilder errorMsg = new StringBuilder();
        Map<String, CloudServer> cloudServerMap = new HashMap<>();
        // 查询全部虚拟机
        List<CloudServer> list = cloudServerRepository.queryProxy().col(GenericEntity::getDeleted).eq(0).list();
        ResourceAssignParam resourceAssignParam = new ResourceAssignParam();
        String mainName = "杨露,李晨,周永伦,刘晓磊,吴尧";
        for (CloudServer cloudServer : list) {
            if (cloudServer.getPrivateIps() == null || "[]".equals(cloudServer.getPrivateIps()) || "NULL".equals(cloudServer.getPrivateIps())) {
                continue;
            }
            logger.info("虚拟机存量ip：{}", JSONObject.toJSONString(cloudServer.getPrivateIps()));
            try {
                JSONArray privateIps = JSON.parseArray(cloudServer.getPrivateIps());
                for (Object privateIp : privateIps) {
                    PrivateIpModel ipModel = JSON.parseObject(privateIp.toString(), PrivateIpModel.class);
                    if (ipModel.getAddress() != null) {
                        cloudServerMap.put(ipModel.getAddress(), cloudServer);
                    }
                }
            }catch (Exception e){
                logger.warn("跳过深信服机器IP:{}", e.getMessage());
            }
        }
        for (ImportCloudServerTemplate importCloudServerTemplate : importCloudServerTemplates) {
            // 防止导入空行
            if (importCloudServerTemplate.getIp() == null || importCloudServerTemplate.getManager() == null) {
                if (importCloudServerTemplate.getIp() == null) {
                    ipNullMsg.append(importCloudServerTemplate.getIndexNo()).append(";");
                }
                if (importCloudServerTemplate.getManager() == null) {
                    managerNullMsg.append(importCloudServerTemplate.getIndexNo()).append(";");
                }
                continue;
            }
            if (cloudServerMap.containsKey(importCloudServerTemplate.getIp())) {
                CloudServer cloudServer = cloudServerMap.get(importCloudServerTemplate.getIp());
                String manager = null;
                String managerString = importCloudServerTemplate.getManager();
                if (managerString.contains("、") || managerString.contains("，")) {
                    managerString = managerString.replace("、", ",").replace("，", ",");
                }
                List<String> managers = Arrays.asList(managerString.split(","));
                // 获取负责人名称
                manager = getManager(mainName, manager, managers);
                // 获取用户信息
                com.bocloud.sms.entity.User user = smsRpcService.userDetail(manager);
                if (user == null){
                    logger.warn("当前用户不存在：{}", manager);
                    continue;
                }
                try {
                    List<Long> ids = new ArrayList<>();
                    ids.add(cloudServer.getId());
                    resourceAssignParam.setIds(ids);
                    // 如果当前虚拟机包含租户信息则先回收
                    if (cloudServer.getTenantId() != null) {
                        BocloudResult computer = resourceAllocateServiceImpl.reclaim(resourceAssignParam, ResourceCategory.valueOf("Computer"), requestContext);
                        if (computer.isFailed()) {
                            logger.info("资源回收失败，不进行分配操作：{}", cloudServer.getName());
                            reclaimFaileMsg.append(cloudServer.getName()).append(":").append(computer.getMessage()).append(";");
                            errorNumber++;
                            continue;
                        }
                    }
                    // 分配用户信息
                    if (user.getTenantId() == null) {
                        logger.info("当前用户不在任何租户下：{}", user.getName());
                        notTenantOfUserMsg.append(user.getName()).append(";");
                        errorNumber++;
                        continue;
                    }
                    resourceAssignParam.setVendorType(VendorType.VMWARE.getName());
                    resourceAssignParam.setUserId(user.getId());
                    resourceAssignParam.setTenantId(user.getTenantId());
                    List<Long> tenantIds = new ArrayList<>();
                    tenantIds.add(user.getTenantId());
                    resourceAssignParam.setTenantIds(tenantIds);
                    BocloudResult computer = resourceAllocateServiceImpl.assign(JSONObject.parseObject(JSONObject.toJSONString(resourceAssignParam)), ResourceCategory.valueOf("Computer"), requestContext);
                    if (computer.isFailed()) {
                        logger.info("资源分配失败：{}", cloudServer.getName());
                        assignFaileMsg.append(cloudServer.getName()).append(":").append(computer.getMessage()).append(";");
                        errorNumber++;
                    } else {
                        successNum++;
                    }
                } catch (Exception e) {
                    logger.error("虚拟机index_no" + importCloudServerTemplate.getIndexNo() + "导入分配异常:", e);
                    throw new IllegalArgumentException("虚拟机index_no" + importCloudServerTemplate.getIndexNo() + "导入分配异常:", e);
                }
            }
        }
        this.sendNotice(true, "共" + importCloudServerTemplates.size() + "条，分配成功" + successNum + "条", requestContext);
    }

    private static String getManager(String mainName, String manager, List<String> managers) {
        // 判断是否包含主要名称
        Boolean isHasMainName = false;
        for (String s : managers) {
            if (s.contains("-")) {
                s = s.split("-")[0];
            }
            if (mainName.contains(s)) {
                manager = s;
                isHasMainName = true;
                break;
            }
        }
        // 如果没有则取第一个
        if (!isHasMainName) {
            manager = managers.get(0);
        }
        return manager;
    }


    /**
     * 查询云主机列表(自服务专用)
     *
     * @author sxp
     * @since 2023/8/1
     */
    @Override
    public BocloudResult<GridBean<CloudServer>> listForTenant(Pager pager, RequestContext context) {
        GridBean<CloudServer> gridBean;
        try {
            JSONObject configJson = smsSystemConfigService.getJSONObjectByCode("resourceChangeVendorTypes");
            if (configJson == null) {
                logger.error("资源变更云平台类型未配置");
                return new BocloudResult<>(false, "查询失败:资源变更云平台类型未配置");
            }
            String value = configJson.getString("resourceChangeVendorTypes");
            if (value != null) {
                value = value.trim();
            }
            List<String> vendorTypes = JSON.parseArray(value, String.class);

            List<Param> params = Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>());
            Boolean simple = Optional.ofNullable(pager.getSimple()).orElse(false);

            Map<String, String> sorter = Optional.ofNullable(pager.getSorter()).orElse(Maps.newLinkedHashMap());
            if (sorter.getClass().equals(HashMap.class)) {
                sorter = new LinkedHashMap<>(sorter);
                pager.setSorter(sorter);
            }
            sorter.put("vendorId", Common.ZERO);
            sorter.put("name", Common.ZERO);

            Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
            Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);

            int total;
            List<CloudServer> list = new ArrayList<>(0);
            if (simple) {
                total = this.cloudServerRepository.countForTenant(params, vendorTypes);
                List<SimpleBean> beans = this.cloudServerRepository.listForTenant(params, sorter, vendorTypes);
                gridBean = new GridBean(1, 1, total, beans);
            } else {
                total = this.cloudServerRepository.vmCountForTenant(params, vendorTypes);
                list = this.cloudServerRepository.listForTenant(page, rows, params, sorter, vendorTypes);
                gridBean = new GridBean<>(page, rows, total, list);
            }

            if (!simple) {
                Map<String, String> allAzUuidNameMap = sangforAzService.getAllAzUuidNameMap();

                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 = new HashMap<>();
                Map<Long, String> projectMap = new HashMap<>();
                Map<Long, String> businessMap = new HashMap<>();
                Map<Long, String> tenantMap = new HashMap<>();

                if (!userIds.isEmpty()) {
                    userMap = smsUserService.listUsersByIds(userIds).stream()
                            .collect(Collectors.toMap(User::getId, User::getName));
                }
                if (!projectIds.isEmpty()) {
                    projectMap = smsProjectService.listProjectsByIds(projectIds).stream()
                            .collect(Collectors.toMap(Project::getId, Project::getName));
                }
                if (!businessIds.isEmpty()) {
                    businessMap = smsBusinessService.listBusinesssByIds(businessIds).stream()
                            .collect(Collectors.toMap(Business::getId, Business::getName));
                }
                if (!tenantIds.isEmpty()) {
                    tenantMap = smsTenantService.listTenantsByIds(tenantIds).stream()
                            .collect(Collectors.toMap(Tenant::getId, Tenant::getName));
                }

                String azUuid, azName;
                for (CloudServer server : list) {
                    azUuid = server.getAzUuid();
                    if (StringUtils.isNotEmpty(azUuid)) {
                        azName = allAzUuidNameMap.get(azUuid);
                        if (StringUtils.isNotEmpty(azName)) {
                            server.setAzName(azName);
                        }
                    }

                    // 设置云主机归属信息
                    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());

                    CloudProvider provider = CloudProvider.valueOf(server.getVendorType());
                    if (CloudProvider.VMWARE == provider) {
                        Volume volume = volumeRepository.getSystemDisk(server.getId());
                        if (null != volume) {
                            server.setSystemDiskSize(volume.getSize());
                        }
                    }
                    if (CloudProvider.TIANYI == provider || CloudProvider.HUAWEI == provider
                            || CloudProvider.HCSO == 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("查询云主机列表(自服务专用)", e);
            return new BocloudResult<>(false, "查询云主机列表(自服务专用):" + e.getMessage());
        }
    }


    private void handleSangforOsInfo(CloudServer server) {
        String osCategory = server.getOsCategory();
        String osName = server.getOsName();
        if (osCategory == null) {
            osCategory = "";
        }
        if ("l2664".equals(osCategory)) {
            server.setOsCategory("Linux");
            switch (osName) {
                case "aCenter":
                    server.setOsName("深信服云计算平台（Sangfor Cloud Platform）");
                    break;
                case "linux-suse":
                    server.setOsName("SUSE Linux");
                    break;
                case "linux-redflag":
                    server.setOsName("红旗Linux");
                    break;
                case "linux-neokylin":
                    server.setOsName("中标麒麟");
                    break;
                case "linux-neoshine":
                    server.setOsName("中标普华Linux");
                    break;
                case "linux-deepin":
                    server.setOsName("深度Linux");
                    break;
                case "linux-ubuntu":
                    server.setOsName("Ubuntu");
                    break;
                case "linux-centos":
                    server.setOsName("CentOS");
                    break;
                case "linux-debian":
                    server.setOsName("Debian GNU/Linux");
                    break;
                case "linux-oracle":
                    server.setOsName("Oracle Linux");
                    break;
                case "linux-redhat":
                    server.setOsName("Red Hat Enterprise Linux");
                    break;
                case "linux-fedora":
                    server.setOsName("Fedora");
                    break;
                default:
                    server.setOsName("未知");
                    return;
            }
            return;
        }

        switch (osCategory) {
            // Windows
            case "ws1964":
                server.setOsCategory("Windows");
                server.setOsName("Server 2019（64位）");
                break;
            case "ws1664":
                server.setOsCategory("Windows");
                server.setOsName("Server 2016（64位）");
                break;
            case "ws1264":
                server.setOsCategory("Windows");
                server.setOsName("Server 2012（64位）");
                break;
            case "ws08":
                server.setOsCategory("Windows");
                server.setOsName("Server 2008（32位）");
                break;
            case "ws0864":
                server.setOsCategory("Windows");
                server.setOsName("Server 2008（64位）");
                break;
            case "ws03":
                server.setOsCategory("Windows");
                server.setOsName("Server 2003（32位）");
                break;
            case "ws0364":
                server.setOsCategory("Windows");
                server.setOsName("Server 2003（64位）");
                break;
            case "win10":
                server.setOsCategory("Windows");
                server.setOsName("Microsoft Windows 10（32位）");
                break;
            case "win1064":
                server.setOsCategory("Windows");
                server.setOsName("Microsoft Windows 10（64位）");
                break;
            case "win8":
                server.setOsCategory("Windows");
                server.setOsName("Microsoft Windows 8（32位）");
                break;
            case "win864":
                server.setOsCategory("Windows");
                server.setOsName("Microsoft Windows 8（64位）");
                break;
            case "win7":
                server.setOsCategory("Windows");
                server.setOsName("Microsoft Windows 7（32位）");
                break;
            case "win764":
                server.setOsCategory("Windows");
                server.setOsName("Microsoft Windows 7（64位）");
                break;
            case "wxp":
                server.setOsCategory("Windows");
                server.setOsName("Microsoft Windows XP（32位）");
                break;
            case "wxp64":
                server.setOsCategory("Windows");
                server.setOsName("Microsoft Windows XP（64位）");
                break;
            case "w2k":
                server.setOsCategory("Windows");
                server.setOsName("Microsoft Windows 2000");
                break;

            // Linux
            case "l26":
                server.setOsCategory("Linux");
                server.setOsName("Linux 3.X/2.6 Kernel（32位）");
                break;
            case "l2664":
                server.setOsCategory("Linux");
                server.setOsName("Linux 3.X/2.6 Kernel（64位）");
                break;
            case "l24":
                server.setOsCategory("Linux");
                server.setOsName("Linux 2.4 Kernel（32位）");
                break;
            case "l2464":
                server.setOsCategory("Linux");
                server.setOsName("Linux 2.4 Kernel（64位）");
                break;

            // 其他
            case "other":
                server.setOsCategory("其他");
                server.setOsName("32位系统");
                break;
            case "other64":
                server.setOsCategory("其他");
                server.setOsName("64位系统");
                break;
            default:
                server.setOsCategory("未知");
                server.setOsName("未知");
                return;
        }
    }

    /**
     * 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);
                Assert.notNull(vendor, "云平台不存在");
                // 公有云云主机节点4合1,私有云云主机节点不计数
                if (Arrays.asList(PUBLIC_CLOUDS).contains(vendor.getType())) {
                    vmCount = cloudServerRepository.vendorCount(Arrays.asList(PUBLIC_CLOUDS));
                    vmCount += vm;
                    vmCount = vmCount % LICENSE_NODE_COUONT > 0 ? vmCount / LICENSE_NODE_COUONT + 1 : vmCount / LICENSE_NODE_COUONT;
                }
            }
            List<String> types = Arrays.asList(new String[]{CloudProvider.F5.name()});
            int nodeCount = pmCount + vmCount + cloudVendorRepository.listByTypes(types, null).size();
            if (nodeCount > licenseSerivce.license().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) {
        logger.info("虚拟机创建VmGenericParam参数{}", JSONObject.toJSONString(params));
        String password = params.getPassword();
        if (!StringUtils.isEmpty(password)) {
            Encryptor encryptor = new AESEncrptor();
            try {
                password = encryptor.decrypt(password.trim(), null);
                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();
        Long projectId = params.getProjectId();
        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);
            Assert.notNull(vendor, "云平台不存在");
            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, projectId, 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;
                    newParams.setSystemDiskName(serverName);
                } else {
                    if (CloudProvider.AZURE == provider) {
                        serverName = name + "-" + IDFactory.instance().mac();
                        newParams.setSystemDiskName(name + "-" + 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 = null;
                if (CloudProvider.SANGFOR.name().equals(vendor.getType())) {
                    JSONObject obj = JSONObject.parseObject(JSONObject.toJSONString(params));
                    obj.put("isNewlyCreated", true); // isNewlyCreated 创建全新虚拟机参数标识
                    procResult = serverOperationHelper.prepareSangfor(obj, context, vendor, process, i, count);
                } else {
                    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)) {
                            cloudServer.setResourceLabel(resourceLabel);
                        }
                        if (null != projectId && 0L != projectId) {
                            cloudServer.setProjectId(projectId);
                        }
                        cloudServerRepository.update(cloudServer);
                    }
                    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);
                                        //发送消息给cop
                                        resourceTaskNotice.sendLogicalMessage(cloudServer, ResourceTaskNotice.Action.UPDATE);
                                    }
                                }
                            }
                        } 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, "创建任务已经下发，正在执行……");
    }

    private BocloudResult cloneSmart(VmGenericParam vmGenericParam, RequestContext context) {
        try {

            Assert.notNull(vmGenericParam.getId(), "需要指定源云主机");
            CloudServer server = cloudServerRepository.query(vmGenericParam.getId());
            Assert.notNull(server, "id为" + vmGenericParam.getId() + "云主机不存在");
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "id为" + server.getVendorId() + "云平台不存在");
            CloudProvider provider = CloudProvider.valueOf(vendor.getType());

            BocloudResult<ServerBuilder> getProcessResult = serverOperationHelper.getProcess(provider, vendor, context);
            Assert.isTrue(getProcessResult.isSuccess(), getProcessResult.getMessage());
            ServerBuilder serverBuilder = getProcessResult.getData();

            BocloudResult<ProcessResult> prepareResult = serverOperationHelper.prepare(vmGenericParam, context, vendor, serverBuilder);
            Assert.isTrue(prepareResult.isSuccess(), prepareResult.getMessage());
            final ProcessResult processResult = prepareResult.getData();

            taskExecutor.execute(() -> {
                String prefix = "克隆云主机" + server.getName();
                String path = CloudServer.class.getSimpleName() + "_" + server.getId();
                OperateResult operateResult = new OperateResult(true, "", vendor.getType().toLowerCase() + ".vm",
                        MapTools.simpleMap(Common.VENDORID, vendor.getId()),
                        OperateCategory.ResourceEvent, context);
                try (BocloudACLock lock = lockFactory.getACLock(path)) {
                    Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "当前存在互斥任务，请稍后再试");

                    BocloudResult<CloudServer> buildResult = serverOperationHelper.builder(vendor.getType(),
                            vendor.getId(), processResult.getCloudServer(), context, serverBuilder, null);
                    Assert.isTrue(buildResult.isSuccess(), buildResult.getMessage());

                    operateResult.setSuccess(true);
                    operateResult.setMessage(prefix + "成功");
                    resourceEventPublisher.send(operateResult);
                } catch (Exception e) {
                    logger.error(prefix + "失败：{}", e.getMessage(), e);
                    operateResult.setSuccess(false);
                    operateResult.setMessage(prefix + "失败：" + e.getMessage());
                    resourceEventPublisher.send(operateResult);
                }
            });
            return new BocloudResult<>(true, "任务已经下发，正在执行...");
        } catch (Exception e) {
            logger.error("克隆云主机失败：{}", e.getMessage(), e);
            return new BocloudResult<>(false, e.getMessage());
        }
    }

    private BocloudResult sangforVmClone(VmGenericParam vmGenericParam, CloudVendor vendor, CloudServer server, RequestContext context) throws InterruptedException {
        try {
            String instanceId = server.getInstanceId();
            Assert.notNull(instanceId, "云主机实例id为空");

            logger.info("虚拟机克隆vmGenericParam参数：{}", JSONObject.toJSONString(vmGenericParam));

            // 深信服虚拟机克隆
            SangforServerModel model = new SangforServerModel();
            com.bocloud.ims.service.utils.BeanUtils.copyPropertiesIgnoreNull(vmGenericParam, model);
            model.setVmid(instanceId);
            model.setStorage(vmGenericParam.getStorage());
            model.setSourceVmId(instanceId);
            model.setStart(vmGenericParam.getStart());
            model.setHa(vmGenericParam.getHa());
            model.setGroup(vmGenericParam.getCategoryId());
            model.setCloneType(vmGenericParam.getCloneType());
            model.setInterfaceType(vmGenericParam.getInterfaceType());
            model.setMac(vmGenericParam.getMac());
            model.setBvsId(vmGenericParam.getBvsId());
            model.setIp(vmGenericParam.getIp());
            model.setMask(vmGenericParam.getMask());
            model.setGateway(vmGenericParam.getGateway());
            model.setPrimaryDns(vmGenericParam.getPrimaryDns());
            model.setSecondaryDns(vmGenericParam.getSecondaryDns());
            model.setHostname(vmGenericParam.getHostname());
            model.setDisableNet(vmGenericParam.getDisableNet());
            model.setStoragePolicy(vmGenericParam.getStorage_policy());
            model.setAlwaysTryHost(vmGenericParam.getAlwaysTryHost());
            model.setRemark(vmGenericParam.getRemark());
            model.setPortUuid(vmGenericParam.getPortUuid());

            Network network = networkRepository.getByNetId(vmGenericParam.getBvsId(), vendor.getId());
            if (network != null) {
                model.setBridgename(network.getName());
            }

            List<CloudServer> cloudServers = cloudServerRepository.listByVid(server.getVendorId());
            // 前端填写虚拟机IP与数据库实际虚拟机IP比较判断是否重复
            BocloudResult bclResult = checkIpRepeat(cloudServers, vmGenericParam.getIp(), RequestContext.Catalog.Manager);
            if (bclResult.isFailed()) {
                return bclResult;
            }
            logger.info("虚拟机克隆model参数：{}", JSONObject.toJSONString(model));

            CloudServer cloudServer = new CloudServer();
            cloudServer.setName(model.getName());
            cloudServer.setVendorId(vendor.getId());
            cloudServer.setStatus("BUILDING");
            cloudServer.setDeleted(false);
            cloudServer.setGmtCreate(new Date());
            cloudServer.setGmtModify(new Date());
            cloudServer.setRecycle(false);
            cloudServer.setVendorName(vendor.getName());
            cloudServerRepository.save(cloudServer);

            String vendorVersion = vendor.getVersion();
            String operate = vendor.getType().toLowerCase() + ".vm";

            new Thread(() -> {
                long begin = System.currentTimeMillis();

                String message = null;
                BocloudResult result = serverDriver.cloneSangfor(vendor.getUuid(), null, model);
                if (result.isFailed()) {
                    cloudServerRepository.remove(cloudServer.getId(), context.getTarget());

                    message = "虚拟机创建失败：" + result.getMessage();
                    logger.error(message);
                    resourceEventPublisher.send(new OperateResult(false, message, operate,
                            MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));

                    return;
                }

                long timeout = 5L * 60 * 1000;   // 虚拟机创建、克隆超时时间设为5分钟
                long sleepTime = 5L * 1000;      // 虚拟机创建、克隆睡眠时间设为5秒钟
                long start = System.currentTimeMillis();
                if ("6.8".equals(vendorVersion)) {
                    String serverListStr = JSON.toJSONString(result.getData());
                    List<SangforServerModel> serverModelList = JSON.parseArray(serverListStr, SangforServerModel.class);
                    if (serverModelList != null && !serverModelList.isEmpty()) {
                        SangforServerModel serverModel = serverModelList.get(0);
                        String newVmInstanceId = serverModel.getInstanceId();

                        boolean waitIp = false;
                        List<SangforNetwork> networks = serverModel.getNetworks();
                        if (networks == null || networks.isEmpty()) {
                            waitIp = true;
                            message = "虚拟机创建成功，正在等待网络信息的生成...";
                        } else {
                            message = "虚拟机创建成功";
                        }
                        logger.info(message);
                        resourceEventPublisher.send(new OperateResult(true, message, operate,
                                MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));

                        long cost;
                        Object data;
                        while (waitIp) {
                            logger.info("正在等待网络信息的生成...");
                            try {
                                Thread.sleep(sleepTime);
                            } catch (InterruptedException e) {
                                //ignore
                            }
                            result = serverDriver.detail(newVmInstanceId, vendor.getUuid(), null);
                            if (result.isFailed()) {
                                logger.warn("查询虚拟机{}信息失败", serverModel.getName());
                                continue;
                            }
                            data = result.getData();
                            serverModel = JSON.parseObject(JSON.toJSONString(data), SangforServerModel.class);
                            if (serverModel != null) {
                                networks = serverModel.getNetworks();
                                if (networks != null && !networks.isEmpty()) {
                                    logger.info("已经获取到网络信息");
                                    waitIp = false;
                                    break;
                                }
                            }
                            cost = System.currentTimeMillis() - start;
                            if (cost > timeout) {
                                break;
                            }
                        }

                        Long userId = 1L;
                        List<Server> hosts = serverRepository.listByVendor(vendor.getId());
                        Map<String, Server> hostMap = new HashMap<>();
                        for (Server host : hosts) {
                            hostMap.put(host.getUuid(), host);
                        }
                        List<DataStore> dataStores = dataStoreRepository.listByVendor(vendor.getId());
                        Map<String, DataStore> dataStoreMap = Maps.newHashMap();
                        for (DataStore dataStore : dataStores) {
                            dataStoreMap.put(dataStore.getGuid(), dataStore);
                        }

                        CloudServer newServer = SangforConvertUtils.convertCloudServerForV68(serverModel, hostMap);
                        com.bocloud.ims.service.utils.BeanUtils.copyPropertiesIgnoreNull(newServer, cloudServer);
                        cloudServerRepository.update(cloudServer);
                        SangforV68Transporter.saveUpdateVolume(volumeRepository, cloudServer, serverModel, userId, dataStoreMap);

                        if (waitIp) {
                            message = "虚拟机创建成功,等待网络信息的生成超时，等待同步信息后获得完整的虚拟机信息";
                        } else {
                            message = "虚拟机创建成功,已经获取到网络信息";
                        }
                        logger.info(message);
                        resourceEventPublisher.send(new OperateResult(true, message, operate,
                                MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));

                        Boolean isAddShterm = cloudServer.getIsAddShterm();
                        if (isAddShterm == null) {
                            isAddShterm = Boolean.TRUE;
                        }
                        // 向堡垒机发送新增云主机的消息
                        if (isAddShterm) {
                            shtermService.addShterm(cloudServer);
                        }
                    } else {
                        cloudServer.setStatus("STOPPED");
                        cloudServerRepository.update(cloudServer);
                        message = "虚拟机创建成功,但是未获取到虚拟机的信息，等待同步信息后获得完整的虚拟机信息";
                        logger.warn(message);
                        resourceEventPublisher.send(new OperateResult(true, message, operate,
                                MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                    }
                    long cost = System.currentTimeMillis() - begin;
                    logger.info("克隆虚拟机耗时{}ms", cost);
                } else {
                    if ("full".equals(model.getCloneType())) {
                        timeout = 20L * 60 * 1000;   //全量虚拟机克隆耗时较长
                        sleepTime = 30L * 1000;
                    }
                    Boolean flag = false;
                    int i = 1;
                    while (System.currentTimeMillis() - start < timeout) {
                        try {
                            Thread.sleep(sleepTime);
                        } catch (InterruptedException e) {
                            logger.error("虚拟机克隆失败", e);
                        }
                        BocloudResult bocloudResult = serverDriver.list(vendor.getUuid(), null, model.getName());
                        if (bocloudResult.isFailed() || bocloudResult.getData() == null) {
                            break;
                        }
                        List<SangforServerModel> serverModelList = JSON.parseArray(JSON.toJSON(bocloudResult.getData()).toString(), SangforServerModel.class);
                        List<CloudServer> servers = SangforConvertUtils.serverConver(serverModelList);
                        List<Volume> volumes = SangforConvertUtils.volumeConver(serverModelList);
                        logger.info("第{}次查询创建结果：\nserver:{}\nvolume:{}\n", i++, JSONObject.toJSONString(servers), JSONObject.toJSONString(volumes));
                        for (CloudServer svr : servers) {
                            String name = svr.getName();
                            String status = svr.getStatus();
                            if (!name.equals(model.getName())) {
                                continue;
                            }
                            if (!"RUNNING".equals(status) && !"STOPPED".equals(status)) {
                                break;
                            }
                            // 同步虚拟机信息
                            com.bocloud.ims.service.utils.BeanUtils.copyPropertiesIgnoreNull(svr, cloudServer);
                            // 克隆时给虚拟机绑定服务类型和规格
                            createServiceSku(cloudServer, volumes, vendor);
                            // 添加虚拟机卷
                            Map<String, Long> dataStoreIdMap = dataStoreRepository.listByVendor(vendor.getId()).stream()
                                    .filter(e -> "VS".equals(e.getType()) || "OTHER".equals(e.getType())).collect(Collectors.toMap(DataStore::getGuid, DataStore::getId));
                            volumes.forEach(e -> {
                                e.setVendorId(vendor.getId());
                                e.setServerId(cloudServer.getId());
                                e.setDataStoreId(dataStoreIdMap.get(e.getDataStoreUuid()));
                                e.setGmtCreate(new Date());
                                e.setGmtModify(new Date());
                                e.setCreatorId(1L);
                                e.setMenderId(1L);
                                e.setDeleted(false);
                                e.setBootVolume(true);
                            });
                            cloudServerRepository.update(cloudServer);
                            volumeRepository.batchSave(volumes, volumes.size());
                            flag = true;
                            break;
                        }
                        if (flag) {
                            logger.info("信息同步完成...");
                            message = "虚拟机创建成功";
                            resourceEventPublisher.send(new OperateResult(true, message, operate,
                                    MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                            break;
                        }
                    }
                    boolean isTimeout = System.currentTimeMillis() - start > timeout;
                    if (isTimeout) {
                        cloudServerRepository.remove(cloudServer.getId(), context.getTarget());
                        message = "虚拟机创建超时，删除虚拟机信息";
                        resourceEventPublisher.send(new OperateResult(false, message, operate,
                                MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                    }
                    if (flag) {
                        Boolean isAddShterm = cloudServer.getIsAddShterm();
                        if (isAddShterm == null) {
                            isAddShterm = Boolean.TRUE;
                        }
                        // 向堡垒机发送新增云主机的消息
                        if (isAddShterm) {
                            shtermService.addShterm(cloudServer);
                        }
                    }
                }
            }).start();
            return new BocloudResult(true, "虚拟机克隆任务已下发");
        } catch (Exception e) {
            return new BocloudResult(false, "虚拟机克隆失败");
        }
    }

    @Override
    public BocloudResult clone(VmGenericParam vmGenericParam, RequestContext context) {
        try {
            Integer count = vmGenericParam.getCount();
            CloudServer bean = new CloudServer();
            BeanUtils.copyProperties(vmGenericParam, bean);
//            bean.setManagerIp(vmGenericParam.getIp());
            String name = bean.getName();
            Long hostId = bean.getHostId();
            CloudServer server = cloudServerRepository.query(bean.getId());
            Assert.notNull(server, "克隆的模板云主机不存在");
            if (BocloudStatus.Server.BUILDING.name().equals(server.getStatus())) {
                return new BocloudResult(false, "不能对正在创建的云主机进行克隆操作");
            }
            Long vendorId = server.getVendorId();
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Assert.notNull(vendor, "云平台不存在");
            if (cloudServerRepository.exists(name, vendor.getId())) {
                return new BocloudResult(false, "云主机名称已存在!");
            }
            if (CloudProvider.SANGFOR.name().equals(vendor.getType())) {
                return this.sangforVmClone(vmGenericParam, vendor, server, context);
            }
            Server host = serverRepository.query(hostId);
            Assert.notNull(host, "目标宿主机不存在");
            List<NetcardOperation> operations = vmGenericParam.getOperations();

            for (NetcardOperation operation : operations) {
                Assert.notNull(operation.getIpv4PoolId(), "网络适配器" + operation.getLabel() + "未指定IP池");
            }


            final Integer finalCount = count;
            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".vm";
                // VCenter分配的云主机IP
                List<Ip> ips = new ArrayList<>();
                List<ProcessResult> processResults = Lists.newArrayList();


                try {
                    List<NetworkCard> cards = networkCardRepository.listByHost(server.getId(), "VM");
                    Map<String, NetworkCard> labelMapCard = cards.stream().collect(Collectors.toMap(NetworkCard::getLabel, Function.identity()));

                    for (int i = 0; i < count; i++) {
                        String serverName = "";
                        if (count == 1) {
                            serverName = name;
                        } else {
                            serverName = name + "_" + (i + 1);
                        }

                        for (int i1 = 0; i1 < operations.size(); i1++) {
                            NetcardOperation netcardOperation = operations.get(i1);
                            netcardOperation.setOperation("EDIT");//这里定死用edit
                            NetworkCard networkCard = labelMapCard.get(netcardOperation.getLabel());
                            Assert.notNull(networkCard, "网络适配器" + netcardOperation.getLabel() + "不存在");
                            String address = netcardOperation.getAddress();
                            List<String> manualIps;
                            try {
                                manualIps = JSON.parseArray(address, String.class);
                            } catch (Exception e) {
                                logger.warn("解析IP出错", e);
                                manualIps = new ArrayList<>();
                            }
                            if (manualIps == null) {
                                manualIps = new ArrayList<>();
                            }
                            Long poolId = netcardOperation.getIpv4PoolId();

                            Ip ip;
                            if (manualIps.isEmpty()) {//自动分配IP
                                BocloudResult<List<Ip>> autoIpsResult = ipService.achievePoolIps(poolId, 1L, null);
                                Assert.isTrue(autoIpsResult.isSuccess(), autoIpsResult.getMessage());
                                ip = autoIpsResult.getData().get(0);
                            } else {//使用手动分配IP
                                String ipAddress = manualIps.get(i);
                                ip = ipRepository.queryProxy().col(Ip::getIp).eq(ipAddress).col(Ip::getPoolId).eq(poolId).oneOrNull();
                                Assert.notNull(ip, "IP地址" + ipAddress + "不存在");
                            }
                            ips.add(ip);
                            netcardOperation.setIp(JSON.parseObject(JSON.toJSONString(ip), IpModel.class));
                        }

                        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, serverDriver, context, vendor, resourceEventPublisher,
                                        ipPoolRepository, smsTenantService, lockFactory, smsProjectService, lvmService, amqpTemplate,
                                        shtermService);
                        BocloudResult<ServerModel> result = builder.prepare(object);
                        if (result.isFailed()) {
                            // 回收IP
                            serverOperationHelper.recycleIp(ips, null, vendor.getId());
                            Assert.isTrue(result.isSuccess(), result.getMessage());
                        }
                        ServerModel model = result.getData();
                        processResults.add(new ProcessResult(model, builder));
                    }

                    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<>();


                    // 保存云主机的一些基本信息
                    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(), server.getId(), 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());
                            //成功后发送消息给cop
                            CloudServer cloudServerToTask = cloudServerRepository.query(cloudServer.getId());
                            if (null != cloudServerToTask) {
                                resourceTaskNotice.sendLogicalMessage(cloudServerToTask, ResourceTaskNotice.Action.ADD);
                            }
                        } 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, "云主机克隆失败：" + e.getMessage(), 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, "云主机克隆失败: " + e.getMessage());
        }
    }

    /**
     * 虚拟机ip地址与数据库已存在地址判重
     *
     * @param serverList 数据库虚拟机列表
     * @param managerIps ip地址
     * @param checkType  判重对象
     * @since 2023.8.28 modify by sxp 模糊匹配privateIps是增加双引号
     */
    public static BocloudResult checkIpRepeat(List<CloudServer> serverList, String managerIps, Catalog checkType) {
        if (StringUtils.isEmpty(managerIps)) {
            return new BocloudResult(true, "success");
        }
        List<String> ipList = ServerOperationHelper.getSangforIpList(managerIps);
        String message;
        for (CloudServer server : serverList) {
            String realIp = server.getPrivateIps();
            if (StringUtils.isEmpty(realIp)) {
                continue;
            }
            for (String target : ipList) {
                if (realIp.indexOf("\"" + target + "\"") >= 0) {
                    switch (checkType) {
                        case Manager:
                            message = "前端输入的IP地址" + target + "与虚拟机(" + server.getName() + ")的IP重复";
                            logger.warn(message);
                            return new BocloudResult(false, message);
                        case Account:
                            message = "申请云主机失败：IP地址" + target + "与虚拟机(" + server.getName() + ")的IP重复";
                            logger.warn(message);
                            return new BocloudResult(false, message);
                        default:
                            break;
                    }
                }
            }
        }
        return new BocloudResult(true, "success");
    }


    private void setNetcardOperation(List<NetcardOperation> operations, NetworkCard netcard) {
        // 新机网卡（多块网卡，只设置一块，其他指定127.0.0.1）
        NetcardOperation operation = new NetcardOperation();
        operation.setName(netcard.getName());
        operation.setOperation("EDIT");
        operation.setLabel(netcard.getLabel());
        operation.setPortType(netcard.getPortType());
        operation.setMac(netcard.getMac());
        operations.add(operation);
    }

    private BocloudResult smartVmToTemplate(VmGenericParam vmGenericParam, String operation, RequestContext context) {
        try {
            Assert.notNull(vmGenericParam, "参数格式不正确");
            Assert.notNull(vmGenericParam.getId(), "需要指定源云主机");

            CloudServer server = cloudServerRepository.query(vmGenericParam.getId());
            Assert.notNull(server, "指定的源云主机不存在");

            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "源云主机所属的云平台不存在");

            Assert.notNull(vmGenericParam.getName(), "需要指定模板名称");
            Assert.notNull(vmGenericParam.getCloudInitSupported(), "需要明确源云主机是否已经安装了Cloud-init");

            ServerModel serverModel = new ServerModel();
            serverModel.setInstanceId(server.getInstanceId());
            serverModel.setName(vmGenericParam.getName());
            serverModel.setRemark(vmGenericParam.getRemark());
            serverModel.setCloudInitSupported(vmGenericParam.getCloudInitSupported());

            taskExecutor.execute(() -> {
                String prefix = "将云主机" + server.getName() + operation + "为模板";
                String path = CloudServer.class.getSimpleName() + "_" + server.getId();
                OperateResult operateResult = new OperateResult(true, "", vendor.getType().toLowerCase() + ".vm",
                        MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context);
                try (BocloudACLock lock = lockFactory.getACLock(path)) {
                    Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "当前存在互斥任务，请稍后重试");

                    CloudServer resultServer;
                    if ("克隆".equals(operation)) {
                        BocloudResult bocloudResult = serverDriver.cloneAsTemplate(vendor.getUuid(), null, serverModel);
                        Assert.isTrue(bocloudResult.isSuccess(), bocloudResult.getMessage());

                        String taskUuid = bocloudResult.getData().toString();
                        VendorTaskMsg task = smartTransporter.getTask(vendor, taskUuid, context.getTarget());
                        Assert.isTrue(task.getSmartSucceed(), task.getSmartFinalErrorMessage());

                        bocloudResult = serverTemplateDriver.detail(vendor.getUuid(), null, task.getTargetUuid());
                        Assert.isTrue(bocloudResult.isSuccess(), bocloudResult.getMessage());

                        ServerModel resultModel = (ServerModel) bocloudResult.getData();
                        resultServer = new CloudServer();
                        smartTransporter.convert(resultModel, resultServer);
                        resultServer.setVendorId(vendor.getId());
                        resultServer.setVendorType(vendor.getType());
                        resultServer.setCreatorId(context.getTarget());
                        resultServer.setGmtCreate(new Date());
                        cloudServerRepository.save(resultServer);

                        smartTransporter.syncNetworkCard(resultServer, resultModel.getNetworkCards(), context.getTarget());

                        List<VolumeModel> imageModels = resultModel.getDiskDevices().stream()
                                .filter(d -> "cdrom".equals(d.getType())).collect(Collectors.toList());
                        smartTransporter.syncServerImage(resultServer, imageModels, context.getTarget());

                        List<VolumeModel> volumeModels = resultModel.getDiskDevices().stream()
                                .filter(d -> "disk".equals(d.getType())).collect(Collectors.toList());
                        smartTransporter.syncServerVolume(resultServer, volumeModels, context.getTarget());
                    } else if ("转化".equals(operation)) {
                        BocloudResult bocloudResult = serverDriver.convertAsTemplate(vendor.getUuid(), null, serverModel);
                        Assert.isTrue(bocloudResult.isSuccess(), bocloudResult.getMessage());

                        resultServer = server;
                        resultServer.setName(vmGenericParam.getName());
                        resultServer.setTemplateSize(0D);
                        resultServer.setIsTemplate(true);
                        cloudServerRepository.update(resultServer);
                        //发送消息给cop
                        resourceTaskNotice.sendLogicalMessage(resultServer, ResourceTaskNotice.Action.UPDATE);
                    } else {
                        throw new UnsupportedOperationException("不支持的operation类型：" + operation);
                    }

                    Image resultImage = new Image();
                    resultImage.setVendorId(resultServer.getVendorId());
                    resultImage.setTemplateId(resultServer.getId());
                    resultImage.setImageUuid(resultServer.getInstanceId());
                    resultImage.setName(resultServer.getName());
                    resultImage.setImageType("TEMPLATE_IMAGE");
                    resultImage.setRemark(resultServer.getRemark());
                    resultImage.setCatalog("VM");
                    resultImage.setStatus("ACTIVE");
                    resultImage.setCreatorId(context.getTarget());
                    resultImage.setGmtCreate(new Date());
                    imageRepository.save(resultImage);

                    operateResult.setSuccess(true);
                    operateResult.setMessage(prefix + "成功");
                    resourceEventPublisher.send(operateResult);
                } catch (Exception e) {
                    logger.error(prefix + "失败：{}", e.getMessage(), e);
                    operateResult.setSuccess(false);
                    operateResult.setMessage(prefix + "失败：" + e.getMessage());
                    resourceEventPublisher.send(operateResult);
                }
            });

            return new BocloudResult(true, "任务已经下发，正在执行...");
        } catch (Exception e) {
            logger.error("将云主机克隆为模板失败: {}", e.getMessage(), e);
            return new BocloudResult(false, "将云主机克隆为模板失败：" + e.getMessage());
        }
    }

    public BocloudResult convertAsTemplate(VmGenericParam vmGenericParam, RequestContext context) {
        try {
            Assert.notNull(vmGenericParam, "参数格式不正确");
            Assert.notNull(vmGenericParam.getId(), "需要指定要转化的源云主机");

            CloudServer server = cloudServerRepository.query(vmGenericParam.getId());
            Assert.notNull(server, "要指定要转化的源云主机不存在");

            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "源云主机所属的云平台不存在");

            if (CloudProvider.SMARTX.name().equals(vendor.getType())) {
                return smartVmToTemplate(vmGenericParam, "转化", context);
            }

            return new BocloudResult(false, "当前云平台不支持此操作");
        } catch (Exception e) {
            logger.error("将云主机转化为模板失败: {}", e.getMessage(), e);
            return new BocloudResult(false, "将云主机转化为模板失败：" + e.getMessage());
        }
    }

    public BocloudResult cloneAsTemplate(VmGenericParam vmGenericParam, RequestContext context) {
        try {
            Assert.notNull(vmGenericParam, "参数格式不正确");
            JSONObject object = JSONObject.parseObject(JSON.toJSONString(vmGenericParam));
            String name = object.getString("name");
            Long hostId = object.getLong("hostId");
            Long id = object.getLong("id");

            CloudServer server = cloudServerRepository.query(id);
            Assert.notNull(server, "克隆的模板云主机不存在");

            Long vendorId = server.getVendorId();
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Assert.notNull(vendor, "获取云供应商失败");

            if (CloudProvider.SMARTX.name().equals(vendor.getType())) {
                return smartVmToTemplate(vmGenericParam, "克隆", context);
            }

            Server host = serverRepository.query(hostId);
            Assert.notNull(host, "目标宿主机不存在");

            if (cloudServerRepository.exists(name, vendor.getId())) {
                return new BocloudResult(false, "云主机名称已存在!");
            }

            object.put("template", server.getName());
            object.put("templateId", server.getId());

            ServerBuilder builder = new VMServerBuilder(cloudServerRepository, serverRepository, dataStoreRepository,
                    networkRepository, networkCardRepository, portGroupRepository, switcherRepository, storeHostRepository,
                    networkHostRepository, ipRepository, resourceRepository, resourceEventRepository, volumeRepository,
                    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(id, "云主机克隆",
                            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);
            Assert.notNull(server, "云主机不存在");
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            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);
                    if (null == store) {
                        return new BocloudResult(false, "要迁移的数据存储不存在");
                    }
                    Volume disk = volumeRepository.query(diskId);
                    if (null == disk) {
                        return new BocloudResult(false, "要迁移的磁盘不存在");
                    }
                    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);
                if (null == store) {
                    return new BocloudResult(false, "数据存储不存在");
                }
                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);
                    if (null == host) {
                        return new BocloudResult(false, "宿主机不存在");
                    }
                    model.setHostName(host.getName());
                } else {
                    host = serverRepository.query(server.getHostId());
                    if (null == host) {
                        return new BocloudResult(false, "数据存储关联的宿主机不存在");
                    }
                }
                model.setClusterName(host.getClusterName());
                model.setVdcName(host.getVdcName());
            } else if (null != hostId && 0L != hostId) {
                host = serverRepository.query(hostId);
                if (null == host) {
                    return new BocloudResult(false, "宿主机不存在");
                }
                model.setHostName(host.getName());
                model.setHostIp(host.getVmotionIp());
                model.setClusterName(host.getClusterName());
                model.setVdcName(host.getVdcName());
                model.setAutoSchedule(false);
                if (CloudProvider.FUSIONSPHERE.name().equalsIgnoreCase(vendor.getType())) {
                    model.setHostUuid(host.getUuid());
                }
            } else if (null != hostId && 0L == hostId) {
                model.setAutoSchedule(true);
            } 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";
                if (CloudProvider.FUSIONSPHERE.name().equalsIgnoreCase(vendor.getType())) {
                    model.setUri(server.getUri());
                }
                BocloudResult result;
                try {
                    result = serverDriver.migrate(vendor.getUuid(), null, model);
                    if (result.isSuccess() && CloudProvider.SMARTX.name().equals(vendor.getType())) {
                        String taskUuid = result.getData().toString();
                        VendorTaskMsg taskMsg = smartTransporter.getTask(vendor, taskUuid, context.getTarget());
                        result = new BocloudResult(taskMsg.getSmartSucceed(), taskMsg.getSmartFinalErrorMessage());
                    }
                    if (result.isSuccess()) {
                        server.setIsTemplate(false);
                        if (null != storeId && 0L != storeId) {
                            BocloudResult detailResult = serverDriver.detail(server.getInstanceId(), vendor.getUuid(), null);
                            ServerModel detailServerModel = JSONObject.parseObject(JSONObject.toJSONString(detailResult.getData()), ServerModel.class);
                            Map<String, DataStore> storeMap = dataStoreRepository.listByVendor(server.getVendorId()).stream().collect(Collectors.toMap(DataStore::getStoreVal, Function.identity(), (m1, m2) -> m2));
                            SyncVmwareUtils sync = new SyncVmwareUtils(dataStoreRepository, serverRepository, networkRepository, storeHostRepository,
                                    networkCardRepository, portGroupRepository, networkHostRepository);
                            // 同步该云主机和存储的关系
                            sync.mergeStoreHost(server.getVendorId(), server.getId(), "VM", detailServerModel.getStores(), storeMap);
                            logger.info("此虚拟机与存储关系完成同步");
                        }
                        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);
                    result = new BocloudResult(false, "云主机迁移失败：" + e.getMessage());
                }
                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);
            Assert.notNull(server, "云主机不存在");
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            Server host = null;
            if (null != hostId) {
                host = serverRepository.query(hostId);
                Assert.notNull(host, "新主机不存在");
                /**
                 * 电科云 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 snapshotType = params.getSnapshotType();
        String path = CloudServer.class.getSimpleName() + "_" + serverId;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudServer server = cloudServerRepository.query(serverId);
            Assert.notNull(server, "云主机不存在");
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "云平台不存在");

            String vendorVersion = vendor.getVersion();
            List<Snapshot> snapshotList = snapshotRepository.listByVMid(serverId);

            // 定时快照cron表达式
            String cron = params.getCron();
            if (!StringUtils.isEmpty(cron)) {
                snapshotTaskService.removeByVmId(serverId);
                String snapTaskName = StringUtils.isEmpty(name) ? server.getName() : name;
                SnapshotTask snapshotTask = new SnapshotTask(snapTaskName, 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:
                case EASYSTACK:
                    break;
                case VMWARE:
                case FUSIONSPHERE:
                    Server host = serverRepository.query(server.getHostId());
                    Assert.notNull(host, "宿主机不存在");
                    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;
                case SANGFOR:
                    if (snapshotList != null && !snapshotList.isEmpty()) {
                        String snapshotName, theType;
                        for (Snapshot snapshot : snapshotList) {
                            snapshotName = snapshot.getName();
                            if (snapshotName == null) {
                                snapshotName = "";
                            }
                            if (snapshotName.equals(name)) {
                                return new BocloudResult(false, "虚拟机已经存在名称为[" + name + "]的快照，请输入不重复的快照名称");
                            }
                            if ("6.8".equals(vendorVersion)) {
                                theType = snapshot.getSnapshotType();
                                if (StringUtils.isNotEmpty(theType) && !theType.equals(snapshotType)) {
                                    snapshotType = theType;
                                }
                            }
                        }
                    }
                    break;
                default:
                    break;
            }
            SnapshotModel model = new SnapshotModel(name, remark, null, server.getInstanceId());
            if ("6.8".equals(vendorVersion) && type == CloudProvider.SANGFOR) {
                model.setSnapshotType(snapshotType);
            }
            if (CloudProvider.FUSIONSPHERE.name().equals(vendor.getType())) {
                Optional.ofNullable(snapshotType).ifPresent(model::setSnapshotType);
            }

            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 = null;
                    if (CloudProvider.FUSIONSPHERE.name().equals(vendor.getType())) {
                        model.setServerUri(server.getUri());
                        model.setIsConsistent(params.getIsConsistent());
                        model.setNeedMemoryShot(params.getNeedMemoryShot());
                        result = snapshotDriver.create(vendor.getUuid(), null, model);
                    } else if (CloudProvider.SANGFOR.name().equals(vendor.getType())) {
                        result = snapshotDriver.create(vendor.getUuid(), null, model);
                    } else {
                        result = serverDriver.snapshot(model, vendor.getUuid(), null);
                    }
                    if (CloudProvider.SMARTX.equals(type) && result.isSuccess()) {
                        String taskUuid = result.getData().toString();
                        VendorTaskMsg taskMsg = smartTransporter.getTask(vendor, taskUuid, context.getTarget());
                        if (taskMsg.getSmartFailed()) {
                            result = new BocloudResult(false, taskMsg.getSmartFinalErrorMessage());
                        } else {
                            SnapshotModel snapshotDetailModel = new SnapshotModel();
                            snapshotDetailModel.setSnapshotUuid(taskMsg.getTargetUuid());
                            snapshotDetailModel.setSnapshotType("VM");
                            result = snapshotDriver.detail(vendor.getUuid(), null, snapshotDetailModel);
                            if (result.isSuccess()) {
                                result.setMessage("云主机创建快照成功");
                            }
                        }
                    }
                    if (result.isSuccess()) {
                        List<Image> images = Lists.newArrayList();
                        List<Snapshot> snaps = Lists.newArrayList();
                        String content = JSONObject.toJSONString(result.getData());
                        switch (type) {
                            case OPENSTACK:
                            case EASYSTACK:
                                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");
                                Long parentSnapId = 0L;
                                if (StringUtils.isNotBlank(snapshot.getParentSnapshotUuid())) {
                                    Snapshot bySnapUuid = snapshotRepository.getBySnapVal(snapshot.getParentSnapshotUuid(), server.getVendorId());
                                    if (null != bySnapUuid) {
                                        parentSnapId = bySnapUuid.getId();
                                    }
                                }
                                snapshot.setParentId(parentSnapId);
                                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;
                            case SMARTX:
                                SnapshotModel snapshotResultModel = (SnapshotModel) result.getData();
                                Snapshot snapshotResult = new Snapshot();
                                smartTransporter.convert(snapshotResultModel, snapshotResult);
                                snapshotResult.setTenantId(server.getTenantId());
                                snapshotResult.setVendorId(vendor.getId());
                                snapshotResult.setVmId(server.getId());
                                snapshotResult.setVmValue(snapshotResultModel.getVmValue());
                                snapshotResult.setCreatorId(userId);
                                snapshotResult.setGmtCreate(new Date());
                                snapshotRepository.save(snapshotResult);
                                break;
                            case FUSIONSPHERE:
                                SnapshotModel snapshotModel = JSONObject.parseObject(content, SnapshotModel.class);
                                Snapshot newSnapshot = new Snapshot();
                                BeanUtils.copyProperties(snapshotModel, newSnapshot);
                                if (null == newSnapshot.getSize()) {
                                    newSnapshot.setSize(0);
                                }
                                newSnapshot.setVmId(serverId);
                                newSnapshot.setVendorId(vendor.getId());
                                newSnapshot.setCreatorId(userId);
                                newSnapshot.setGmtCreate(new Date());
                                if (StringUtils.isNotBlank(newSnapshot.getParentSnapshotUuid())) {
                                    Snapshot bySnapUuid = snapshotRepository.getBySnapUuid(newSnapshot.getParentSnapshotUuid(), server.getVendorId());
                                    Assert.notNull(bySnapUuid, "父快照不存在");
                                    newSnapshot.setParentId(bySnapUuid.getId());
                                } else {
                                    newSnapshot.setParentId(0L);
                                }
                                newSnapshot.setTenantId(server.getTenantId());
                                newSnapshot.setProjectId(server.getProjectId());
                                newSnapshot.setCatalog(context.getCatalog());
                                if (context.getCatalog().equals(Catalog.User) || context.getCatalog().equals(Catalog.Tenant)) {
                                    newSnapshot.setExpiredTime(server.getExpiredTime());
                                }
                                snapshotRepository.save(newSnapshot);
                                break;
                            case SANGFOR:
                                boolean flag = false;
                                BocloudResult bolcoudResult;
                                for (int i = 0; i < 10; i++) {
                                    bolcoudResult = snapshotDriver.list(vendor.getUuid(), null, server.getInstanceId());
                                    if (bolcoudResult.isSuccess()) {
                                        List<SangforSnapshotModel> snapshotModelList = (List<SangforSnapshotModel>) bolcoudResult.getData();
                                        boolean created = snapshotModelList.stream().map(SangforSnapshotModel::getName)
                                                .collect(Collectors.toList()).contains(name);
                                        if (!created) {
                                            continue;
                                        }
                                        SangforServerModel serverModel = new SangforServerModel();
                                        serverModel.setVmid(server.getInstanceId());
                                        serverModel.setSnapshotModels(snapshotModelList);
                                        List<SangforServerModel> sangforServerModels = Collections.singletonList(serverModel);
                                        List<Snapshot> snapshots = SangforConvertUtils.snapshotConver(sangforServerModels);
                                        for (Snapshot item : snapshots) {
                                            if (!name.equals(item.getName())) {
                                                continue;
                                            }
                                            item.setVmId(serverId);
                                            item.setVendorId(vendor.getId());
                                            if (item.getCreatorId() == null) {
                                                item.setCreatorId(userId);
                                            }
                                            if (item.getDeleted() == null) {
                                                item.setDeleted(false);
                                            }
                                            snapshotRepository.save(item);
                                            flag = true;
                                        }
                                        if (flag) {
                                            break;
                                        }
                                    }
                                    logger.info("sleeep 2 seconds waiting for snapshot...");
                                    TimeUnit.SECONDS.sleep(2);
                                }
                                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 snapshot 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, "云主机不存在");
            String status = vm.getStatus();
            Integer oldCpu = vm.getCpu();
            BigDecimal oldMemory = vm.getMemory();

            Integer newCpu = bean.getCpu();
            BigDecimal newMemory = bean.getMemory();

            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());
            model.setIsTemplate(bean.getTemplate());
            switch (type) {
                case SMARTX:
                    if (!CollectionUtils.isEmpty(bean.getOperations())) {
                        List<NetcardOperation> netcards = new ArrayList<>();
                        for (NetcardOperation netcardOperation : bean.getOperations()) {
                            if ("CREATE".equals(netcardOperation.getOperation())) {
                                Network network;
                                if (context.getCatalog().equals(Catalog.Tenant) || context.getCatalog().equals(Catalog.User)) {
                                    PortGroup portGroup = portGroupRepository.query(netcardOperation.getNetworkId());
                                    Assert.notNull(portGroup, "未找到id为" + netcardOperation.getNetworkId() + "的网络");
                                    network = networkRepository.getByNetId(portGroup.getGroupVal());
                                    Assert.notNull(network, "未找到uuid为" + portGroup.getGroupVal() + "的网络");
                                } else {
                                    network = networkRepository.query(netcardOperation.getNetworkId());
                                    Assert.notNull(network, "未找到id为" + netcardOperation.getNetworkId() + "的网络");
                                }

                                Switcher switcher = switcherRepository.query(network.getSwitcherId());
                                Assert.notNull(network, "未找到id为" + network.getSwitcherId() + "的虚拟交换机");

                                List<Subnet> subnets = subnetRepository.listByNetwork(network.getId());
                                Assert.notEmpty(subnets, "未找到网络[" + network.getName() + "]包含的子网");

                                NetcardOperation netcard = new NetcardOperation();
                                netcard.setOperation(netcardOperation.getOperation());
                                netcard.setNetworkUuid(network.getNetworkUuid());
                                netcard.setOvs(switcher.getOvsbrName());
                                netcard.setModel(netcardOperation.getModel());
                                netcard.setMac(netcardOperation.getMac());
                                netcard.setLink(netcardOperation.getLink());
                                netcard.setVlan(subnets.get(0).getVlan());
                                netcards.add(netcard);
                            } else if ("REMOVE".equals(netcardOperation.getOperation())) {
                                NetworkCard networkCard = networkCardRepository.query(netcardOperation.getNetworkCardId());
                                Assert.notNull(networkCard, "未找到id为" + netcardOperation.getNetworkCardId() + "的网卡");

                                NetcardOperation netcard = new NetcardOperation();
                                netcard.setOperation(netcardOperation.getOperation());
                                netcard.setMac(networkCard.getMac());
                                netcards.add(netcard);
                            }
                        }
                        model.setOperations(netcards);
                    }
                    break;
                case VMWARE:
                    if ("RUNNING".equals(status)) {
                        if (newCpu != null && oldCpu != null && newCpu < oldCpu) {
                            return new BocloudResult(false, "开机状态下，新CPU大小不能小于原CPU大小" + oldCpu);
                        }
                        if (newMemory != null && oldMemory != null && newMemory.intValue() < oldMemory.intValue()) {
                            return new BocloudResult(false, "开机状态下，新内存大小不能小于原内存大小" + oldMemory.intValue() + "GB");
                        }
                        // 如果原内存小于4GB，新内存不能超过3GB sxp:2023.7.21
                        if (newMemory != null && oldMemory != null && oldMemory.intValue() < 4 && newMemory.intValue() >= 4) {
                            return new BocloudResult(false, "开机状态下，原内存为" + oldMemory.intValue() + "GB时，新内存最大值为3GB。如果要设置更大的内存，请先进行关机操作。");
                        }
                    }
                    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 EASYSTACK:
                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;
                case FUSIONSPHERE:
                    model.setUri(vm.getUri());
                    break;
                case SANGFOR:
                    if ("RUNNING".equals(status)) {
                        if (newCpu != null && oldCpu != null && newCpu.intValue() != oldCpu.intValue()) {
                            return new BocloudResult(false, "要使修改后的CPU配置生效，请先进行关机操作。修改完配置后再重新开机。");
                        }
                        if (newMemory != null && oldMemory != null && newMemory.intValue() != oldMemory.intValue()) {
                            return new BocloudResult(false, "要使修改后内存配置生效，请先进行关机操作。修改完配置后再重新开机。");
                        }
                    }
                    model = new ServerModel();
                    model.setInstanceId(vm.getInstanceId());
                    if (StringUtils.isNotEmpty(bean.getName())) {
                        model.setName(bean.getName());
                    }
                    if (newCpu != null) {
                        model.setCpu(newCpu);
                    }
                    if (newMemory != null) {
                        model.setMemory(newMemory);
                    }
                    model.setCfgstorage(bean.getCfgstorage());
                    model.setRemark(bean.getRemark());
                    break;
                default:
                    break;
            }
            ServerModel serverModel = model;
            // 启动一个线程
            new Thread(() -> {
                BocloudResult result = null;
                if (CloudProvider.SMARTX.name().equals(vendor.getType())) {
                    result = new BocloudResult(true, "未做任何更改");
                    // 先修改基本信息
                    boolean basicModified = false;
                    ServerModel basicParamModel = new ServerModel();
                    basicParamModel.setInstanceId(vm.getInstanceId());
                    if (StringUtils.isNotEmpty(bean.getName()) && !Objects.equals(bean.getName(), vm.getName())) {
                        basicParamModel.setName(bean.getName());
                        basicModified = true;
                    }
                    if ((StringUtils.isNotEmpty(bean.getRemark()) && !Objects.equals(bean.getRemark(), vm.getRemark()))) {
                        basicParamModel.setRemark(bean.getRemark());
                        basicModified = true;
                    }
                    if (null != bean.getCpu() && !Objects.equals(bean.getCpu(), vm.getCpu())) {
                        basicParamModel.setCpu(bean.getCpu());
                        basicModified = true;
                    }
                    if (null != bean.getMemory() && !Objects.equals(bean.getMemory(), vm.getMemory())) {
                        basicParamModel.setMemory(bean.getMemory());
                        basicModified = true;
                    }
                    if (null != bean.getHa() && !Objects.equals(bean.getHa(), vm.getIsHA())) {
                        basicParamModel.setHa(bean.getHa());
                        basicModified = true;
                    }
                    if (basicModified) {
                        result = serverDriver.modify(vendor.getUuid(), vm.getRegionId(), serverModel);
                        if (result.isSuccess()) {
                            String taskUuid = result.getData().toString();
                            VendorTaskMsg taskMsg = smartTransporter.getTask(vendor, taskUuid, context.getTarget());
                            result = new BocloudResult(taskMsg.getSmartSucceed(), taskMsg.getSmartFinalErrorMessage());
                        }
                    }
                    // 修改基本信息成功后再修改网卡信息
                    if (result.isSuccess() && !CollectionUtils.isEmpty(serverModel.getOperations())) {
                        Map<String, List<NetcardOperation>> netcardOperations = serverModel.getOperations().stream()
                                .collect(groupingBy(NetcardOperation::getOperation));
                        if (result.isSuccess() && netcardOperations.containsKey("CREATE")) {
                            ServerModel netcardParamModel = new ServerModel();
                            netcardParamModel.setInstanceId(vm.getInstanceId());
                            netcardParamModel.setOperations(netcardOperations.get("CREATE"));
                            result = serverDriver.attachNetwork(vendor.getUuid(), null, netcardParamModel);
                            if (result.isSuccess()) {
                                String taskUuid = result.getData().toString();
                                VendorTaskMsg taskMsg = smartTransporter.getTask(vendor, taskUuid, context.getTarget());
                                result = new BocloudResult(taskMsg.getSmartSucceed(), taskMsg.getSmartFinalErrorMessage());
                            }
                        }
                        if (result.isSuccess() && netcardOperations.containsKey("REMOVE")) {
                            String macAddresses = netcardOperations.get("REMOVE").stream()
                                    .map(NetcardOperation::getMac).collect(Collectors.joining(","));
                            result = serverDriver.detachNetwork(vendor.getUuid(), null, vm.getInstanceId(), macAddresses);
                            if (result.isSuccess()) {
                                String taskUuid = result.getData().toString();
                                VendorTaskMsg taskMsg = smartTransporter.getTask(vendor, taskUuid, context.getTarget());
                                result = new BocloudResult(taskMsg.getSmartSucceed(), taskMsg.getSmartFinalErrorMessage());
                            }
                        }
                    }
                    // 最终仍然成功的话查询云主机详情
                    if (result.isSuccess()) {
                        result = serverDriver.detail(vm.getInstanceId(), vendor.getUuid(), null);
                    }
                } 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()) {
                        Object dataObj = result.getData();
                        String content = null;
                        if (dataObj != null) {
                            content = JSON.toJSONString(dataObj);
                        }
                        CloudServer server = null;
                        if (StringUtils.isNotEmpty(content)) {
                            logger.info("modify server content:{}", content);

                            if (type == CloudProvider.SANGFOR && "6.8".equals(vendor.getVersion())) {
                                SangforServerModel sangforServerModel = JSONObject.parseObject(content, SangforServerModel.class);
                                Map<String, Server> hostMap = new HashMap<>();
                                server = SangforConvertUtils.convertCloudServerForV68(sangforServerModel, hostMap);
                            } else {
                                server = JSONObject.parseObject(content, CloudServer.class);
                            }
                        }
                        if (server == null) {
                            // 校验接口返回的修改后的虚拟机信息 sxp:2023.6.6
                            String message = "修改虚拟机信息失败，接口未返回修改后的虚拟机信息";
                            resourceEventPublisher.send(new OperateResult(false, message, operate,
                                    MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                            return;
                        }
                        switch (type) {
                            case SMARTX:
                                result.setMessage("重新配置云主机成功");
                                ServerModel resultModel = (ServerModel) result.getData();
                                smartTransporter.syncNetworkCard(vm, resultModel.getNetworkCards(), context.getTarget());
                                smartTransporter.convert(resultModel, vm);
                                break;
                            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(), 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());
                                List<NetcardOperation> operations = serverModel.getOperations();
                                if (!ListTool.isEmpty(serverModel.getOperations())) {
                                    vm.setPrivateIps(server.getPrivateIps());
                                }
                                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;
                            case FUSIONSPHERE:
                                vm.setName(server.getName());
                                vm.setRemark(server.getRemark());
                                vm.setCpu(server.getCpu());
                                vm.setMemory(server.getMemory());
                                vm.setIsTemplate(server.getIsTemplate());
                                break;
                            case SANGFOR:
                                vm.setName(server.getName());
                                vm.setRemark(server.getRemark());
                                if (server.getCpu() != null) {
                                    vm.setCpu(server.getCpu());
                                }
                                if (server.getMemory() != null) {
                                    vm.setMemory(server.getMemory());
                                }
                                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);
                        //发送消息给cop
                        resourceTaskNotice.sendLogicalMessage(vm, ResourceTaskNotice.Action.UPDATE);
                    }
                    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));
                    // 向堡垒机发送修改消息
                    String vendorType = vm.getVendorType();
                    if (CloudProvider.VMWARE.name().equals(vendorType)
                            || CloudProvider.SANGFOR.name().equals(vendorType)) {
                        shtermService.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(), e);
            return new BocloudResult(false, e.getMessage());
        }
    }

    /**
     * 修改数据库中的云主机信息
     *
     * @author sxp
     * @since 2023/8/3
     */
    @Override
    public BocloudResult modifyServerOfDb(CloudServer newServer, RequestContext context, String queue) {
        Long serverId = newServer.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(newServer.getName())
                    && !CloudProvider.POWERVC.name().equals(vendor.getType())) {
                boolean flag = cloudServerRepository.exists(newServer.getName(), vendor.getId());
                if (flag) {
                    return new BocloudResult(false, "云主机名称不能重复");
                }
            }

            // 复制属性
            com.bocloud.ims.service.utils.BeanUtils.copyPropertiesIgnoreNull(newServer, vm);
            cloudServerRepository.update(vm);

            return new BocloudResult(true, "修改数据库中的云主机信息成功");
        } catch (Exception e) {
            logger.error("修改数据库中的云主机信息失败:" + e.getMessage(), e);
            return new BocloudResult(false, "修改数据库中的云主机信息失败:" + e.getMessage());
        }
    }


    @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), "请求超时");
            logger.info("remove server id : " + id);
            CloudServer server = cloudServerRepository.get(id);
            Assert.notNull(server, "云主机不存在");
            if (server.getStatus().equals(BocloudStatus.Server.SYNSEXCEPTION.name())) {
                return new BocloudResult(false, "同步异常的云主机不可以删除!");
            }
            Long tenantId = server.getTenantId();
            if (tenantId != null && tenantId > 0) {
                return new BocloudResult(false, "删除虚拟机前请先回收!");
            }
            Boolean deletePublicIp = false;
            Boolean deleteVolume = false;
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            // 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());
                Assert.notNull(hmcPartition, "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, "根磁盘下存在快照，请先删除快照再进行此操作");
                        }
                    }
                }
            }
            // 重置云主机状态
            String oldStaus = server.getStatus();
            server.setStatus("DELETING");
            server.setMenderId(context.getTarget());
            cloudServerRepository.update(server);
            //发送消息给cop
            resourceTaskNotice.sendLogicalMessage(server, ResourceTaskNotice.Action.UPDATE);
            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())
                                    || CloudProvider.HCSO.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 if (CloudProvider.VOLCENGINE.name().equals(vendor.getType())) {
                                // 如果是火山云平台，支持删除云主机的时候选择删除挂载硬盘及浮动ip
                                if (vmDeleteParam.getDeletePublicIp()) {
                                    List<ElasticIp> elasticIps = elasticIpRepository.listByIid(server.getInstanceId(), server.getVendorId());
                                    for (ElasticIp ip : elasticIps) {
                                        ElasticIpModel model = new ElasticIpModel();
                                        model.setElasticIpUuid(ip.getElasticIpUuid());
                                        model.setInstanceType(ip.getInstanceType());
                                        result = elasticIpDriver.disassociate(model, vendor.getUuid(), ip.getRegionId());
                                        if (result.isFailed()) {
                                            logger.error("浮动ip跟随云主机删除时解绑失败:" + result.getMessage());
                                            break;
                                        }
                                        result = elasticIpDriver.release(vendor.getUuid(), ip.getElasticIpUuid(), ip.getRegionId());
                                        if (result.isFailed()) {
                                            logger.error("浮动ip跟随云主机删除失败:" + result.getMessage());
                                            break;
                                        }
                                    }
                                }
                                //注意：云主机删除后，挂载的云硬盘也会跟随删除
                                if (result.isSuccess()) {
                                    result = serverDriver.remove(server.getInstanceId(), server.getName(),
                                            vendor.getUuid(), null);
                                }
                            } else if (CloudProvider.SMARTX.name().equals(vendor.getType())) {
                                result = serverDriver.remove(server.getInstanceId(), server.getName(), vendor.getUuid(),
                                        server.getRegionId());
                                if (result.isSuccess()) {
                                    String taskUuid = result.getData().toString();
                                    VendorTaskMsg taskMsg = smartTransporter.getTask(vendor, taskUuid, context.getTarget());
                                    result = new BocloudResult(taskMsg.getSmartSucceed(), taskMsg.getSmartFinalErrorMessage());
                                }
                            } else if (CloudProvider.FUSIONSPHERE.name().equals(vendor.getType())) {
                                result = serverDriver.remove(server.getUri(), null, vendor.getUuid(),
                                        null);
                            } else if (CloudProvider.SANGFOR.name().equals(vendor.getType())) {
                                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);
                            } else {
                                server.setStatus(oldStaus);
                                cloudServerRepository.update(server);
                            }
                            //发送消息给cop
                            resourceTaskNotice.sendLogicalMessage(server, ResourceTaskNotice.Action.UPDATE);
                            event = new ResourceEvent(id, "云主机删除", "失败", context.getTarget(), new Date(), "VM",
                                    vendor.getId(), context.getCatalog());
                            content = "云主机【" + server.getName() + "】删除失败!" + result.getMessage();
                            logger.error(content);
                        }
                        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());
        }
    }


    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:
                    case HCSO:
                        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);
            Assert.notNull(server, "云主机不存在");
            // 设置云主机归属
            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 || CloudProvider.VOLCENGINE == 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 || CloudProvider.HCSO == provider) {
                List<JSONObject> ips = JSONArray.parseArray(server.getPrivateIps(), JSONObject.class);
                Optional<JSONObject> type =
                        ips.stream().filter(ip -> "floating".equals(ip.getString("type"))).findFirst();
                if (type.isPresent()) {
                    JSONObject object = type.get();
                    ElasticIp elasticIp =
                            elasticIpRepository.querybyInstanceId(object.getString("portId"), server.getVendorId());
                    if (elasticIp != null) {
                        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);
            server.setDiskList(volumes);
            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));
            }
            // 云主机标签
            List<JSONObject> parseArray = JSON.parseArray(server.getResourceLabel(), JSONObject.class);
            if (!ListTool.isEmpty(parseArray)) {
                BocloudResult existsValues = labelServiceImpl.isExistsValues(parseArray);
                if (existsValues.isFailed()) {
                    return existsValues;
                }
                server.setResourceLabel(JSONObject.toJSONString(existsValues.getData()));
                cloudServerRepository.update(server);
            }
            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) {
                        networkCard.setNetworkcardUuid(floatingIp.getNetworkCardUuid());
                        networkCard.setFloatingIp(floatingIp.getFloatingIpAddress());
                        networkCard.setFloatingIpUuid(floatingIp.getFloatingIpUuid());
                    }
                    networkCard.setIpAddress(privateIp);
                    networkCards.add(networkCard);
                }
                server.setNetcards(networkCards);
            }
            //Azure 设置资源组名称
            if (CloudProvider.AZURE == provider) {
                Optional.ofNullable(resourceGroupRepository.query(server.getResourceGroupId())).map(ResourceGroup::getName).ifPresent(server::setResourceGroupName);
            } else if (CloudProvider.SANGFOR == provider) {
                List<Volume> volumesx = volumeRepository.listByServerId(id);
                if (ListTool.isEmpty(volumesx)) {
                    return new BocloudResult(false, "虚拟机存储为空");
                }
                Long dataStoreId = volumesx.get(0).getDataStoreId();
                server.setDatastoreId(dataStoreId);
                DataStore dataStore = dataStoreRepository.query(dataStoreId);
                if (dataStore != null) {
                    server.setDatastore(dataStore.getGuid());
                }
            }
            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 SOFTSTOP:
                        result = softStop(id, context);
                        break;
                    case REBOOT:
                        result = restart(id, context);
                        break;
                    case SOFTREBOOT:
                        result = softRestart(id, context);
                        break;
                    case PAUSE:
                        result = pause(id, context);
                        break;
                    case RECOVERY:
                        result = recovery(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 batchSoftReboot(List<Long> ids, RequestContext context) {
        return batchAction(ids, context, ServerAction.SOFTREBOOT, "软重启");
    }

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

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

    @Override
    public BocloudResult batchPause(List<Long> ids, RequestContext context) {
        return batchAction(ids, context, ServerAction.PAUSE, "暂停");
    }

    @Override
    public BocloudResult batchRecovery(List<Long> ids, RequestContext context) {
        return batchAction(ids, context, ServerAction.RECOVERY, "恢复");
    }

    @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);
    }

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

    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);
    }

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

    /**
     * 处理云主机状态
     *
     * @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();
        //项目ID
        Long projectId = params.getProjectId();
        // 标签
        String resourceLabel = params.getResourceLabel();
        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());
                jsonObject.put("projectId", projectId);
                jsonObject.put("catalog", context.getCatalog().name());
                BocloudResult result = nameRuleService.generate(nameRuleId, jsonObject);
                if (result.isFailed()) {
                    return new BocloudResult(false, "云主机名称生成失败");
                }
                name = String.valueOf(result.getData());
                logger.info("命名规则生成虚拟机名称：" + name);
            }
            // 数据中心
            Vdc vdc = vdcRepository.query(vdcId);
            Assert.notNull(vdc, "数据中心不存在");
            model.setVdcName(vdc.getName());
            if (cloudServerRepository.exists(name, vdc.getVendorId())) {
                return new BocloudResult(false, "此名称已存在!");
            }
            // 云供应商
            CloudVendor vendor = cloudVendorRepository.query(vdc.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            // 宿主机
            Server server = serverRepository.query(hostId);
            Assert.notNull(server, "宿主机不存在");
            model.setHostName(server.getName());
            // 宿主机资源池下创建云主机
            VmResourcePool vmResourcePool = resourcePoolRepository.query(resPoolId);
            Assert.notNull(vmResourcePool, "指定的资源池不存在");
            model.setResPoolName(vmResourcePool.getName());
            // 集群资源池下创建云主机
            if ("CLUSTER".equals(poolOwner)) {
                Cluster cluster = clusterRepository.query(vmResourcePool.getOwner());
                model.setClusterName(cluster.getName());
            }
            // 数据存储
            DataStore dataStore = dataStoreRepository.query(dsId);
            Assert.notNull(dataStore, "指定的数据存储不存在");
            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());
                        Assert.notNull(portGroup, "虚拟网卡不存在");
                        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());
            cloudServer.setResourceLabel(resourceLabel);
            cloudServer.setProjectId(projectId);
            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);
                        //发送消息给cop
                        resourceTaskNotice.sendLogicalMessage(cloudServer, ResourceTaskNotice.Action.UPDATE);
                        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());
                                diskVol.setCategory(convertDiskCategory(diskVol.getCategory()));
                                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());
                        //通知主机资源
                        resourceTaskNotice.sendLogicalMessage(cloudServer, ResourceTaskNotice.Action.DEL);
                    }
                    // 保存资源信息
                    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, "创建失败!");
        }
    }

    /***
     * 数据盘的云盘种类。取值范围：
     *
     * cloud：普通云盘 cloud_efficiency：高效云盘 cloud_ssd：SSD云盘 cloud_essd：ESSD云盘 默认值：cloud
     */
    private String convertDiskCategory(String raw) {
        if ("cloud_efficiency".equalsIgnoreCase(raw)) {
            return VolumeCategory.EFFICIENCY.name();
        }
        if ("cloud_ssd".equalsIgnoreCase(raw)) {
            return VolumeCategory.SSD.name();
        }
        if ("cloud_essd".equalsIgnoreCase(raw)) {
            return VolumeCategory.ESSD.name();
        }
        return VolumeCategory.CLOUD.name();
    }

    @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;
            String labelContent = 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("labelContent")) {
                        labelContent = paramMap.get("labelContent").toString();
                        paramMap.remove("labelContent");
                    }
                }
            }
            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, labelContent, 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);
            Assert.notNull(vendor, "云平台不存在");
            // 指定目标宿主机
            Long hostId = object.getLong("hostId");
            Server host = serverRepository.query(hostId);
            Assert.notNull(host, "目标宿主机不存在");
            // 指定存储
            Long storeId = object.getLong("storeId");
            DataStore dataStore = dataStoreRepository.query(storeId);
            Assert.notNull(dataStore, "宿主机【" + host.getName() + "】下无任何数据存储可用!");
            // 需要克隆的云主机
            List<CloudServer> cloudServers = Lists.newArrayList();
            // 所有需要克隆的云主机磁盘
            List<Volume> volumeList = Lists.newArrayList();
            for (Long serverId : serverIds) {
                CloudServer server = cloudServerRepository.query(serverId);
                Assert.notNull(server, "云主机不存在");
                if (null != server.getTenantId() && server.getTenantId() > 0) {
                    return new BocloudResult(false, "不能对租户的云主机进行克隆操作");
                }
                if (BocloudStatus.Server.BUILDING.name().equals(server.getStatus())) {
                    return new BocloudResult(false, "不能对正在创建的云主机进行克隆操作");
                }
                cloudServers.add(server);
                List<Volume> volumes = volumeRepository.listByServerId(serverId);
                volumeList.addAll(volumes);
            }
            if (ListTool.isEmpty(cloudServers)) {
                return new BocloudResult(false, "暂时没有可以克隆云主机");
            }
            // 判断存储
            int disk = 0;
            int diskSum = volumeList.stream().mapToInt(Volume::getSize).sum();
            if (diskSum >= dataStore.getFreeSpace()) {
                return new BocloudResult(false, "此存储暂不满足所有云主机克隆，请重新选择存储");
            }
            // 选定ipv4
            Long ipv4PoolId = object.getLong("ipPoolId");
            List<Ip> ips4Free = ipRepository.listByPool(ipv4PoolId, Ip.IpStatus.free);
            // 默认克隆不会设置多个ip，所以一个主机一个ip
            if (ListTool.isEmpty(ips4Free) || ips4Free.size() < cloudServers.size()) {
                return new BocloudResult(false, "ipv4池可用ip不足，请重新选择");
            }

            // VCenter分配的云主机IP
            List<Ip> ips = Lists.newArrayList();
            List<ProcessResult> processResults = Lists.newArrayList();
            for (CloudServer server : cloudServers) {
                // 查询模板的网卡
                List<NetworkCard> cards = networkCardRepository.listByHost(server.getId(), "VM");
                if (ListTool.isEmpty(cards)) {
                    return new BocloudResult(false, "云主机模板上无任何网卡");
                }
                List<NetcardOperation> operations = Lists.newArrayList();
                NetworkCard card = cards.get(0);
                setNetcardOperation(ipv4PoolId, operations, card);
                // 分配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);
                }
                // 如果存在多网卡的情况，只设置第一块网卡ip，其他均不设置ip，默认127.0.0.1
                if (cards.size() > 1) {
                    Map<Long, NetworkCard> collect =
                            cards.stream().collect(Collectors.toMap(NetworkCard::getId, Function.identity()));
                    collect.remove(card.getId());
                    for (NetworkCard netcard : collect.values()) {
                        setNetcardOperation(ipv4PoolId, operations, netcard);
                    }
                }
                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());
                Volume systemDisk = volumeRepository.getSystemDisk(server.getId());
                if (null != systemDisk) {
                    jsonObject.put("disk", systemDisk.getSize());
                } else {
                    jsonObject.put("disk", server.getDisk());
                }
                jsonObject.put("account", server.getAccount());
                jsonObject.put("password", server.receivePswd());
                jsonObject.put("storeId", storeId);

                jsonObject.put("datastore", dataStore.getName());
                ServerBuilder builder =
                        new VMServerBuilder(cloudServerRepository, serverRepository, dataStoreRepository, networkRepository,
                                networkCardRepository, portGroupRepository, switcherRepository, storeHostRepository,
                                networkHostRepository, ipRepository, resourceRepository, resourceEventRepository,
                                volumeRepository, serverDriver, context, vendor, resourceEventPublisher,
                                ipPoolRepository, smsTenantService, lockFactory, smsProjectService, lvmService, amqpTemplate,
                                shtermService);
                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<Long> succServerIdList = Lists.newArrayList();
                // 克隆失败的云主机
                List<BocloudResult> failList = Lists.newArrayList();
                List<Long> failServerIdList = 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()) {
                            BocloudResult bocloudResult = new BocloudResult(true,
                                    "【" + cloudServer.getName() + "】克隆成功【" + result.getMessage() + "】");
                            succList.add(bocloudResult);
                            succServerIdList.add(cloudServer.getId());
                            event = new ResourceEvent(cloudServer.getId(), "云主机克隆", "成功", context.getTarget(),
                                    new Date(), "VM", vendor.getId(), context.getCatalog());
                            //克隆成功发送消息给cop
                            CloudServer cloudServerToTask = cloudServerRepository.query(cloudServer.getId());
                            if (null != cloudServerToTask) {
                                resourceTaskNotice.sendLogicalMessage(cloudServerToTask, ResourceTaskNotice.Action.ADD);
                            }
                        } else {
                            BocloudResult bocloudResult = new BocloudResult(true,
                                    "【" + cloudServer.getName() + "】克隆失败【" + result.getMessage() + "】");
                            failList.add(bocloudResult);
                            failServerIdList.add(cloudServer.getId());
                            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";
                        }
                    }
                    // 存在克隆失败的机器，则所有机器回滚删除
                    if (fail > 0) {
                        this.batchRemove(succServerIdList, context);
                    }
                    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, "云主机克隆失败!");
        }
    }

    /**
     * @param operations
     * @param netcard
     * @return void
     * @Author: lxy
     * @Description: 设置网卡
     * @Date 2021/8/25 14:28
     * @Param ipv4PoolId
     * @throws:
     **/
    private void setNetcardOperation(Long ipv4PoolId, List<NetcardOperation> operations, NetworkCard netcard) {
        NetcardOperation operation = new NetcardOperation();
        operation.setName(netcard.getName());
        operation.setOperation("EDIT");
        operation.setIpv4PoolId(ipv4PoolId);
        operation.setLabel(netcard.getLabel());
        operation.setPortType(netcard.getPortType());
        operation.setMac(netcard.getMac());
        operations.add(operation);
    }

    @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);
            Assert.notNull(vendor, "云平台不存在");
            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);
                        Assert.notNull(server, "云主机不存在");
                        // 去掉这个限制   sxp:2023.6.21
                        /*if (null != server.getTenantId() && server.getTenantId() > 0) {
                            return new BocloudResult(false, "不能对租户的云主机进行快照操作");
                        }*/
                        switch (provider) {
                            case OPENSTACK:
                            case EASYSTACK:
                                if (null != server.getProjectId() && 0L != server.getProjectId()) {
                                    BocloudResult<Project> projResult = smsProjectService.detail(server.getProjectId());
                                    if (projResult.isFailed()) {
                                        return new BocloudResult(false, projResult.getMessage());
                                    }
                                    Assert.notNull(projResult.getData(), "云主机所在项目不存在");
                                }
                                break;
                            case VMWARE:
                                Server host = serverRepository.query(server.getHostId());
                                Assert.notNull(host, "宿主机不存在");
                                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 = null;
                        String sangforSnapshotName = null;
                        if (CloudProvider.SANGFOR.name().equals(vendor.getType())) {
                            SimpleDateFormat sdfTem = new SimpleDateFormat("yyyyMMddHHmmss");
                            sangforSnapshotName = server.getName() + "_snapshot_" + sdfTem.format(new Date());
                            model.setName(sangforSnapshotName);
                            if (vendor.getVersion().equals("6.8")) {
                                model.setSnapshotType(params.getSnapType());
                                result = snapshotDriver.create(vendor.getUuid(), null, model);
                                ResourceEvent event = new ResourceEvent(serverId, "创建快照",
                                        result.isSuccess() ? "成功" : "失败", context.getTarget(), new Date(), "VM", vendor.getId(),
                                        context.getCatalog());
                                resourceEventRepository.save(event);
                            } else {
                                result = snapshotDriver.create(vendor.getUuid(), null, model);
                            }
                        } else {
                            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 SANGFOR:
                                boolean flag = false;
                                for (int i = 0; i < 10; i++) {
                                    BocloudResult listResult = snapshotDriver.list(vendor.getUuid(), null, server.getInstanceId());
                                    if (listResult.isSuccess()) {
                                        List<SangforSnapshotModel> data = (List<SangforSnapshotModel>) listResult.getData();
                                        boolean created = data.stream().map(SangforSnapshotModel::getName).collect(Collectors.toList()).contains(sangforSnapshotName);
                                        if (!created) {
                                            continue;
                                        }
                                        SangforServerModel serverModel = new SangforServerModel();
                                        serverModel.setVmid(server.getInstanceId());
                                        serverModel.setSnapshotModels(data);
                                        List<SangforServerModel> sangforServerModels = Collections.singletonList(serverModel);
                                        List<Snapshot> snapshots = SangforConvertUtils.snapshotConver(sangforServerModels);
                                        for (Snapshot snapshot : snapshots) {
                                            if (!sangforSnapshotName.equals(snapshot.getName())) {
                                                continue;
                                            }
                                            snapshot.setVmId(serverId);
                                            snapshot.setVendorId(vendor.getId());
                                            if (snapshot.getCreatorId() == null) {
                                                snapshot.setCreatorId(userId);
                                            }
                                            if (snapshot.getDeleted() == null) {
                                                snapshot.setDeleted(false);
                                            }
                                            snapshotRepository.save(snapshot);
                                            flag = true;
                                        }
                                        if (flag) {
                                            break;
                                        }
                                    }
                                    logger.info("sleeep 2 seconds waiting for snapshot...");
                                    TimeUnit.SECONDS.sleep(2);
                                }
                                return new BocloudResult(true, "快照创建成功");
                            case OPENSTACK:
                            case EASYSTACK:
                                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());
                                if (StringUtils.isNotBlank(snapshot.getParentSnapshotUuid())) {
                                    Snapshot bySnapUuid = snapshotRepository.getBySnapVal(snapshot.getParentSnapshotUuid(), server.getVendorId());
                                    Assert.notNull(bySnapUuid, "父快照不存在");
                                    snapshot.setParentId(bySnapUuid.getId());
                                } else {
                                    snapshot.setParentId(0L);
                                }
                                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 ("softstop".equalsIgnoreCase(action)) {
            return this.softStop(id, context);
        }
        // 暂停
        if ("pause".equalsIgnoreCase(action)) {
            return this.pause(id, context);
        }
        // 休眠
        if ("hibernated".equalsIgnoreCase(action)) {
            return this.hibernated(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 ("convertAsTemplate".equals(action)) {
            return this.convertAsTemplate(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 ("SoftReboot".equalsIgnoreCase(action)) {
            return this.batchSoftReboot(batchOperationParam.getIds(), context);
        } else if ("Start".equalsIgnoreCase(action)) {
            return this.batchStart(batchOperationParam.getIds(), context);
        } else if ("SoftStop".equalsIgnoreCase(action)) {
            return this.batchSoftStop(batchOperationParam.getIds(), context);
        } else if ("Stop".equalsIgnoreCase(action)) {
            return this.batchStop(batchOperationParam.getIds(), context);
        } else if ("Pause".equalsIgnoreCase(action)) {
            return this.batchPause(batchOperationParam.getIds(), context);
        } else if ("Recovery".equalsIgnoreCase(action)) {
            return this.batchRecovery(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 availableSizes(Long id) {
        try {
            CloudServer cloudServer = cloudServerRepository.query(id);
            Assert.notNull(cloudServer, "云主机不存在");
            CloudVendor cloudVendor = cloudVendorRepository.query(cloudServer.getVendorId());
            Assert.notNull(cloudVendor, "平台验证失败");
            List<Flavor> newFlavors = new ArrayList<>();
            List<Flavor> flavors = flavorRepository.listByVendorId(cloudServer.getVendorId(), cloudServer.getRegionId());
            Map<String, Flavor> flavorMap = new HashMap<>();
            for (Flavor flavor : flavors) {
                flavorMap.put(flavor.getFlavorUuid().toLowerCase(), flavor);
            }
            BocloudResult result = serverDriver.availableSizes(cloudServer.getInstanceId(), cloudVendor.getUuid(), cloudServer.getRegionId());
            if (result.isSuccess()) {
                List<FlavorModel> flavorModels = JSONArray.parseArray(JSONObject.toJSONString(result.getData()), FlavorModel.class);
                for (FlavorModel flavorModel : flavorModels) {
                    if (flavorMap.containsKey(flavorModel.getFlavorUuid().toLowerCase())) {
                        newFlavors.add(flavorMap.get(flavorModel.getFlavorUuid().toLowerCase()));
                    }
                }
            }
            return new BocloudResult(true, newFlavors, "查询成功！");
        } catch (Exception e) {
            logger.error("vm availableSizes fail:", e);
            return new BocloudResult(false, "查询失败 : " + e.getMessage());
        }
    }

    @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));
                Assert.notNull(server, "云主机不存在");
                CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
                Assert.notNull(vendor, "云平台不存在");
                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);
        } else if ("listByVendorAndStatus".equalsIgnoreCase(action)) {
            Long vendorId = object.getLong("vendorId");
            String status = object.getString("status");
            String azUuid = object.getString("azUuid");
            List<CloudServer> cloudServers = cloudServerRepository.listByVendorAndStatus(vendorId, status, azUuid);
            return new BocloudResult(true, cloudServers, "查询成功");
        }
        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());
                }
                vmIds.add(-1L);
            }
            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);
            Assert.notNull(server, "云主机不存在");
            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, "流水号配置失败");
        }
    }

    @Override
    public BocloudResult generalize(Long id, RequestContext context) {
        try {
            CloudServer server = cloudServerRepository.get(id);
            Assert.notNull(server, "云主机不存在");
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            if ("RUNNING".equals(server.getStatus())) {
                return new BocloudResult(false, "该操作需要在关机状态下执行");
            }
            ResourceEvent event;
            BocloudResult result = serverDriver.generalize(vendor.getUuid(), server.getRegionId(),
                    server.getInstanceId());
            if (result.isFailed()) {
                event = new ResourceEvent(server.getId(), "通用化失败", "通用化失败！云主机【" + server.getName() + "】",
                        context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                resourceEventRepository.save(event);
                return new BocloudResult(false, "通用化失败！");
            }
            ServerModel serverModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()),
                    ServerModel.class);
            server.setStatus(serverModel.getStatus());
            cloudServerRepository.update(server);
            //发送消息给cop
            resourceTaskNotice.sendLogicalMessage(server, ResourceTaskNotice.Action.UPDATE);
            event = new ResourceEvent(server.getId(), "通用化成功", "通用化成功！云主机【" + server.getName() + "】",
                    context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
            resourceEventRepository.save(event);
            return new BocloudResult(true, "通用化成功！");
        } catch (Exception e) {
            logger.error("server generalize fail:", e);
            return new BocloudResult(false, "通用化失败 : " + e.getMessage());
        }
    }

    @Override
    public BocloudResult attachCdrom(CdromModel cdromModel, RequestContext context) {
        try {
            CloudServer cloudServer = cloudServerRepository.query(cdromModel.getVmId());
            Assert.notNull(cloudServer, "云主机不存在");
            CloudVendor vendor = cloudVendorRepository.query(cloudServer.getVendorId());
            Assert.notNull(vendor, "平台不存在");
            cdromModel.setVmUuid(cloudServer.getUri());

            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".vm";
                String message = "更新VM失败";
                BocloudResult result = serverDriver.attachCdrom(vendor.getUuid(), cdromModel);
                try {
                    if (result.isSuccess()) {
                        cloudServer.setCdRomStatus("fill");
                        cloudServerRepository.update(cloudServer);
                        message = "更新VM成功";
                    } else {
                        logger.error("更新VM失败：" + result.getMessage());
                        message = result.getMessage();
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("VM attachCdrom fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("VM attachCdrom error!", e);
            return new BocloudResult<>(false, "更新失败:" + e.getMessage());

        }
    }

    @Override
    public BocloudResult detachCdrom(CdromModel cdromModel, RequestContext context) {
        try {
            CloudServer cloudServer = cloudServerRepository.query(cdromModel.getVmId());
            Assert.notNull(cloudServer, "云主机不存在");
            CloudVendor vendor = cloudVendorRepository.query(cloudServer.getVendorId());
            Assert.notNull(vendor, "平台不存在");
            cdromModel.setVmUuid(cloudServer.getUri());

            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".vm";
                String message = "更新VM失败";
                BocloudResult result = serverDriver.detachCdrom(vendor.getUuid(), cdromModel);
                try {
                    if (result.isSuccess()) {
                        cloudServer.setCdRomStatus("empty");
                        cloudServerRepository.update(cloudServer);
                        message = "更新VM成功";
                    } else {
                        logger.error("更新VM失败：" + result.getMessage());
                        message = result.getMessage();
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("VM attachCdrom fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("VM detachCdrom error!", e);
            return new BocloudResult<>(false, "更新失败:" + e.getMessage());

        }
    }

    @Override
    public BocloudResult listVmGroups(Long vendorId, String azId, RequestContext context) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Assert.notNull(vendor, "云平台不存在");
            List<SangforServerGroup> sangforServerGroups = serverGroupRepository.listByCondition(vendorId, azId);
            return new BocloudResult(true, sangforServerGroups, "查询成功");
        } catch (Exception e) {
            logger.error("查询虚拟机分组信息失败", e);
            return BocloudResult.FAILED("查询虚拟机分组信息失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult listLabels(Long vendorId, RequestContext context) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Assert.notNull(vendor, "云平台不存在");
            return serverDriver.listLabel(vendor.getUuid(), null);
        } catch (Exception e) {
            logger.error("查询虚拟机标签信息失败", e);
            return BocloudResult.FAILED("查询虚拟机标签信息失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult listcon(Long vendorId, String storage, RequestContext context) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Assert.notNull(vendor, "云平台不存在");

            try {
                InetAddress localHost = Inet4Address.getLocalHost();
                String hostAddress = localHost.getHostAddress();
                logger.info("获取到的本机ip地址为{}", hostAddress);
                if ("192.168.1.64".equals(hostAddress) || "10.8.2.138".equals(hostAddress)) {
                    String str = DataUtil.con;
                    JSONObject returnData = JSONObject.parseObject(str);
                    JSONArray data = returnData.getJSONArray("data");
                    List<SangforConModel> conModels = JSONObject.parseArray(data.toJSONString(), SangforConModel.class);
                    return new BocloudResult<>(true, conModels, "成功");
                }
            } catch (UnknownHostException e) {
                logger.error("获取本机ip地址失败", e);
                return new BocloudResult<>(false, "获取本机ip地址失败");
            }
            return serverDriver.listCon(vendor.getUuid(), null, storage);
        } catch (Exception e) {
            logger.error("查询网络设备连接列表失败", e);
            return BocloudResult.FAILED("查询网络设备连接列表失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult listIso(Long vendorId, String storage, RequestContext context) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Assert.notNull(vendor, "云平台不存在");

            //返回数据
            //List<SangforIsosModel> isoModels = new ArrayList<>();
            if (!vendor.getVersion().equalsIgnoreCase("6.8")) {
                return serverDriver.listIso(vendor.getUuid(), null, storage);
            } else {
                List<Image> list = imageRepository.listByVendorId(vendorId);
                List<Image> isoList = new ArrayList<>(list.size() / 2);
                String sangforImageFormat;
                for (Image image : list) {
                    if ("iso".equalsIgnoreCase(image.getSangforImageFormat())) {
                        isoList.add(image);
                    }
                }
                return new BocloudResult<>(true, isoList, "获取成功");
            }
        } catch (Exception e) {
            logger.error("获取iso列表失败", e);
            return BocloudResult.FAILED("获取iso列表失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult vnc(Long vendorId, String instanceId, RequestContext context) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Assert.notNull(vendor, "云平台不存在");
            JSONObject authentication = JSONObject.parseObject(vendor.getAuthentication());
            String address = authentication.getString("address");
            String version = authentication.getString("version");
            String protocol = null;
            String host = null;

            if (address.contains("://")) {
                protocol = address.substring(0, address.indexOf("://"));
                host = address.substring(address.indexOf("//") + 2).replace("/", "");
            } else {
                protocol = "http";
                host = address.replace("/", "");
            }

            BocloudResult bocloudResult = serverDriver.vncLogin(vendor.getUuid(), null, instanceId);
            if (bocloudResult.isFailed()) {
                return bocloudResult;
            }

            if ("6.8".equals(version)) {
                // {"remote_console":{"protocol":"vnc","type":"novnc","url":"https://172.22.150.20:4430/openstack/compute/v2/open-vnc-console?token_id=8056c33d-d8a6-4568-9b3a-2f6a99504b23"}}
                Object data = bocloudResult.getData();
                String dataText = JSON.toJSONString(data);
                if (FastjsonUtils.isJSONObject(dataText)) {
                    JSONObject json = JSON.parseObject(dataText);
                    JSONObject consoleJson = json.getJSONObject("remote_console");
                    String url = consoleJson.getString("url");
                    return new BocloudResult(true, url, "vnc查询成功");
                } else {
                    return new BocloudResult(false, "返回结果不是json格式");
                }
            } else {
                BocloudResult vnc = serverDriver.vnc(vendor.getUuid(), null, instanceId);
                if (vnc.isSuccess()) {
                    JSONObject result = JSONObject.parseObject(vnc.getData().toString());
                    result.put("protocol", protocol);
                    result.put("host", host);
                    return new BocloudResult(true, result, "vnc查询成功");
                } else {
                    return vnc;
                }
            }
        } catch (Exception e) {
            logger.error("获取虚拟机vnc控制台失败", e);
            return BocloudResult.FAILED("获取虚拟机vnc控制台失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult vmDataStore(Long id) {
        try {
            List<Volume> volumes = volumeRepository.listByServerId(id);
            if (ListTool.isEmpty(volumes)) {
                return new BocloudResult(false, "虚拟机存储为空");
            }
            Long dataStoreId = volumes.get(0).getDataStoreId();
            DataStore dataStore = dataStoreRepository.query(dataStoreId);
            return new BocloudResult(true, dataStore, "查询成功");
        } catch (Exception e) {
            logger.error("查询失败", e);
            return BocloudResult.FAILED("查询失败");
        }
    }

    @Override
    public BocloudResult pricing(ApplicationParam applicationParam, RequestContext context) {
        try {
            LocationModel location = applicationParam.getLocation();
            JSONObject configs = applicationParam.getConfigs();
            EmptionModel emption = applicationParam.getEmption();
            Long vendorId = location.getVendorId();
            String regionId = location.getRegion();
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Assert.notNull(vendor, "云平台不存在");
            CloudProvider provider = CloudProvider.valueOf(vendor.getType());
            BocloudResult bocloudResult;
            Integer count = emption.getCount();
            DurationModel duration = emption.getDuration();
            Integer amount = duration.getAmount();  // 订购时长
            DurationModel.Mode mode = duration.getMode();
            Assert.notNull(mode, "订购类型未知");
            PricingModel pricingModel = new PricingModel();
            String chargeType = null;

            switch (provider) {
                case HUAWEI:

                    JSONArray dataDisk = configs.getJSONArray("dataDisk");
                    String rootVolumeType = configs.getString("rootVolumeType");
                    Integer rootSize = configs.getInteger("rootSize");
                    Flavor flavor = flavorRepository.query(configs.getLong("flavorId"));
                    Assert.notNull(flavor, "规格不存在");
                    Image image = imageRepository.query(configs.getLong("imageId"));
                    Assert.notNull(image, "镜像不存在");
                    String osCategory = image.getOsCategory();
                    String suffix = null;
                    Integer periodType = null;
                    Integer periodNum = amount;
                    if ("Linux".equals(osCategory)) {
                        suffix = ".linux";
                    } else if ("Windows".equals(osCategory)) {
                        suffix = ".win";
                    } else {
                        return new BocloudResult(false, "镜像种类未知");
                    }
                    // 华为云订购包年/包月产品的周期类型。  0：天  2：月  3：年  4：小时
                    if (DurationModel.Mode.Hour.equals(mode)) {
                        periodType = 4;
                        chargeType = ChargeCommon.ChargeMode.PostCharge.name();
                    } else if (DurationModel.Mode.Month.equals(mode)) {
                        periodType = 2;
                        chargeType = ChargeCommon.ChargeMode.PreCharge.name();
                    } else if (DurationModel.Mode.Year.equals(mode)) {
                        periodType = 3;
                        chargeType = ChargeCommon.ChargeMode.PreCharge.name();
                    }

                    List<PricingVmModel> vms = new ArrayList<>();
                    List<PricingDiskModel> disks = new ArrayList<>();
                    pricingModel.setChargeType(chargeType);
                    pricingModel.setVms(vms);
                    pricingModel.setDisks(disks);
                    for (int i = 0; i < count; i++) {
                        // 虚拟机
                        PricingVmModel pricingVmModel = new PricingVmModel();
                        pricingVmModel.setVmSpec(flavor.getFlavorUuid() + suffix);
                        pricingVmModel.setPeriodType(periodType);
                        pricingVmModel.setPeriodNum(periodNum);
                        vms.add(pricingVmModel);
                        // 系统盘
                        PricingDiskModel rootDiskModel = new PricingDiskModel();
                        rootDiskModel.setDiskSpec(rootVolumeType);
                        rootDiskModel.setSize(rootSize);
                        rootDiskModel.setPeriodType(periodType);
                        rootDiskModel.setPeriodNum(periodNum);
                        disks.add(rootDiskModel);
                        // 数据盘
                        if (!dataDisk.isEmpty()) {
                            for (int j = 0; j < dataDisk.size(); j++) {
                                JSONObject dataDiskJo = dataDisk.getJSONObject(j);
                                String dataDiskCategory = dataDiskJo.getString("dataDiskCategory");
                                Integer dataDiskSize = dataDiskJo.getInteger("dataDiskSize");
                                PricingDiskModel dataDiskModel = new PricingDiskModel();
                                dataDiskModel.setDiskSpec(dataDiskCategory);
                                dataDiskModel.setSize(dataDiskSize);
                                dataDiskModel.setPeriodType(periodType);
                                dataDiskModel.setPeriodNum(periodNum);
                                disks.add(dataDiskModel);
                            }
                        }
                    }
                    logger.info("询价请求参数：{}", JSONObject.toJSONString(pricingModel));
                    bocloudResult = billingDriver.pricing(vendor.getUuid(), regionId, pricingModel);
                    break;
                case TIANYI:
                    JSONArray dataDiskTianYi = configs.getJSONArray("dataDisk");
                    String systemDiskCategory = configs.getString("systemDiskCategory");
                    Integer systemDiskSize = configs.getInteger("systemDiskSize");

                    Integer cpu = configs.getInteger("cpu");
                    Integer memory = configs.getInteger("memory");


                    Flavor flavorTianYi = flavorRepository.query(configs.getLong("flavorId"));
                    Assert.notNull(flavorTianYi, "规格不存在");
                    Image imageTianYi = imageRepository.query(configs.getLong("imageId"));
                    Assert.notNull(imageTianYi, "镜像不存在");
                    String osCategoryTianYi = imageTianYi.getOsCategory();


                    // 华为云订购包年/包月产品的周期类型。  0：天  2：月  3：年  4：小时
                    if (DurationModel.Mode.Hour.equals(mode)) {
                        chargeType = ChargeCommon.ChargeMode.PostCharge.name();
                    } else if (DurationModel.Mode.Month.equals(mode)) {
                        chargeType = ChargeCommon.ChargeMode.PreCharge.name();
                    } else if (DurationModel.Mode.Year.equals(mode)) {
                        chargeType = ChargeCommon.ChargeMode.PreCharge.name();
                    }

                    // 订购数量及时长
                    pricingModel.setChargeType(chargeType);
                    pricingModel.setCount(count);
                    pricingModel.setAmount(amount);
                    // 云主机
                    pricingModel.setCpu(cpu);
                    pricingModel.setMemory(memory);
                    pricingModel.setOsType(osCategoryTianYi);
                    // 磁盘
                    pricingModel.setSystemDiskCategory(systemDiskCategory);
                    pricingModel.setSystemDiskSize(systemDiskSize);
                    bocloudResult = billingDriver.pricing(vendor.getUuid(), pricingModel);
                    break;
                default:
                    return new BocloudResult(false, "不支持询价");
            }
            return bocloudResult;
        } catch (Exception e) {
            logger.error("询价失败", e);
            return new BocloudResult(false, e.getMessage());
        }
    }

    /**
     * 自动创建平台规格
     *
     * @param cloudServer
     * @param volumes
     * @param vendor
     */
    public void createServiceSku(CloudServer cloudServer, List<Volume> volumes, CloudVendor vendor) {
        try {
            String serviceCode;
            String spec = null;
            String code = null;
            ServiceSku sku;
            if (null != cloudServer) {
                serviceCode = vendor.getType().toLowerCase() + ".standard.server";
                List<ServiceCategory> serviceCategories = cosInternalService.listServiceCategories(serviceCode);
                Assert.notNull(serviceCategories, "不存在对应的服务类型");
                Assert.isTrue(serviceCategories.size() == 1, "服务类型只允许存在一种");
                ServiceCategory serviceCategory = serviceCategories.get(0);
                Long categoryId = serviceCategory.getId();

                SkuParams skuParams = new SkuParams();
                int currentCpu = cloudServer.getCpu();
                int currentMem = cloudServer.getMemory().intValue();
                spec = "[{\"unit\":\"核\",\"specName\":\"cpu\",\"displayName\":\"CPU\",\"specValue\":\"" + currentCpu + "\"},{\"unit\":\"GB\",\"specName\":\"memory\",\"displayName\":\"内存\",\"specValue\":\"" + currentMem + "\"}]";
                code = "standard." + currentCpu + "C" + currentMem + "G";

                skuParams.setCatalogId(1L);
                skuParams.setServiceCode(serviceCode);
                skuParams.setCategoryId(categoryId);
                skuParams.setSpec(spec);
                skuParams.setCode(code);
                sku = cosInternalService.createServiceSku(skuParams);
                Assert.notNull(sku, "对应规格不存在, 云主机名称为:" + cloudServer.getName());
                cloudServer.setCategoryId(categoryId);
                cloudServer.setSkuId(sku.getId());
            }
            if (!CollectionUtils.isEmpty(volumes)) {
                serviceCode = vendor.getType().toLowerCase() + ".standard.volume";
                List<ServiceCategory> serviceCategories = cosInternalService.listServiceCategories(serviceCode);
                Assert.notNull(serviceCategories, "不存在对应的服务类型");
                Assert.isTrue(serviceCategories.size() == 1, "服务类型只允许存在一种");
                ServiceCategory serviceCategory = serviceCategories.get(0);
                Long categoryId = serviceCategory.getId();

                SkuParams skuParams = new SkuParams();
                for (Volume volume : volumes) {
                    int currentDisk = volume.getSize();
                    spec = "[{\"unit\":\"GB\",\"specName\":\"disk\",\"displayName\":\"磁盘\",\"specValue\":\"" + currentDisk + "\"}]";
                    code = "standard." + currentDisk + "G";

                    skuParams.setCatalogId(2L);
                    skuParams.setServiceCode(serviceCode);
                    skuParams.setCategoryId(categoryId);
                    skuParams.setSpec(spec);
                    skuParams.setCode(code);
                    sku = cosInternalService.createServiceSku(skuParams);
                    Assert.notNull(sku, "对应规格不存在, 磁盘容量为:" + volume.getSize());
                    volume.setCategoryId(categoryId);
                    volume.setSkuId(sku.getId());
                }

            }
        } catch (Exception e) {
            logger.error("深信服创建(克隆)虚拟机过程中自动创建规格失败", e);
        }
    }
}
