package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.compute.ServerDriver;
import com.bocloud.cmp.driver.storage.VolumeDriver;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.*;
import com.bocloud.cmp.model.common.*;
import com.bocloud.cmp.model.common.OrderMessage.Operation;
import com.bocloud.cmp.vm.model.VmGenericParam;
import com.bocloud.common.encrypt.AESEncrptor;
import com.bocloud.common.encrypt.Encryptor;
import com.bocloud.common.enums.BoCloudService;
import com.bocloud.common.model.*;
import com.bocloud.common.model.OperateResult.OperateCategory;
import com.bocloud.common.utils.*;
import com.bocloud.ims.common.utils.DateUtils;
import com.bocloud.ims.entity.common.CloudService;
import com.bocloud.ims.entity.common.Recycled;
import com.bocloud.ims.entity.common.User;
import com.bocloud.ims.entity.dto.OaMessageBean;
import com.bocloud.ims.entity.dto.OaNotifyTodoAppResult;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.nsx.NsxSegment;
import com.bocloud.ims.entity.resource.nsx.NsxTierOne;
import com.bocloud.ims.interfaces.resource.*;
import com.bocloud.ims.repository.common.NsxSegmentRepository;
import com.bocloud.ims.repository.common.NsxTierOneRepository;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.service.builder.ServerBuilder;
import com.bocloud.ims.service.common.ZjkyOAService;
import com.bocloud.ims.service.engine.ResSchedulerEngine;
import com.bocloud.ims.service.internal.CosInternalService;
import com.bocloud.ims.service.internal.SmsUserService;
import com.bocloud.ims.service.internal.worker.DiskFormatService;
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.task.ResourceTaskNotice;
import com.bocloud.ims.service.utils.*;
import com.bocloud.nms.enums.ChargeCommon;
import com.bocloud.nms.enums.OrderItemStatus;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections.map.HashedMap;
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.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.net.InetAddress;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 云主机订购业务类实现类
 *
 * @author weiwei
 */
@Service("vmApplyService")
public class VMApplyServiceImpl implements VMApplyService {

    private static Logger logger = LoggerFactory.getLogger(VMApplyServiceImpl.class);
    private static OperateCategory operateCategory = OperateCategory.ResourceEvent;
    @Autowired
    private CloudServerRepository cloudServerRepository;
    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private ImageRepository imageRepository;
    @Autowired
    private DataStoreRepository dataStoreRepository;
    @Autowired
    private ServerRepository serverRepository;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private SnapshotRepository snapshotRepository;
    @Autowired
    private ServerDriver serverDriver;
    @Autowired
    private StoreHostRepository storeHostRepository;
    @Autowired
    private NetworkRepository networkRepository;
    @Autowired
    private PortGroupRepository portGroupRepository;
    @Autowired
    private PortGroupRelationRepository portGroupRelationRepository;
    @Autowired
    private NetworkHostRepository networkHostRepository;
    @Autowired
    private NetworkCardRepository networkCardRepository;
    @Autowired
    private ResourceRepository resourceRepository;
    @Autowired
    private IpRepository ipRepository;
    @Autowired
    private ObjectRelationRepository objectRelationRepository;
    @Autowired
    private VolumeRepository volumeRepository;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private VdcRepository vdcRepository;
    @Autowired
    private ClusterRepository clusterRepository;
    @Autowired
    private CmdbMessagePublisher cmdbMessagePublisher;
    @Autowired
    private ServerOperationHelper serverOperationHelper;
    @Autowired
    private ServerConfigRepository serverConfigRepository;
    @Autowired
    private DiskFormatService diskFormatService;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private FlavorRepository flavorRepository;
    @Autowired
    private IpService ipService;
    @Autowired
    private ResSchedulerEngine resSchedulerEngine;
    @Autowired
    private LvmService lvmService;
    @Autowired
    private CloudServerService cloudServerService;
    @Autowired
    private CosInternalService cosInternalService;
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private IpPoolRepository ipPoolRepository;
    @Autowired
    private NsxTierOneRepository tierOneRepository;
    @Autowired
    private NsxSegmentRepository segmentRepository;
    @Autowired
    private VendorProjectService vendorProjectService;
    @Autowired
    private ResourceEventRepository resourceEventRepository;
    @Autowired
    private PoolGroupRelationRepository poolGroupRelationRepository;
    @Autowired
    private SubnetRepository subnetRepository;
    @Autowired
    private NetworkInterfaceRepository networkInterfaceRepository;
    @Autowired
    private ElasticIpRepository elasticIpRepository;
    @Autowired
    private ElasticIpService elasticIpService;
    @Autowired
    private OSTenantRepository osTenantRepository;
    @Autowired
    private PoolGroupRepository poolGroupRepository;
    @Autowired
    private VolumeDriver volumeDriver;
    @Autowired
    private ResourceTaskNotice resourceTaskNotice;
    @Autowired
    private ZjkyOAService zjkyOAService;
    @Autowired
    private SmsUserService smsUserService;
    @Autowired
    private NetworkService networkService;
    @Autowired
    private SangforVlanGroupRepositpry sangforVlanGroupRepositpry;
    @Autowired
    private SangforServerGroupRepository serverGroupRepository;

    @Override
    public BocloudResult apply(ApplicationParam param) {
        try {
            String templateName = null;
            String templatePassword = null;

            Assert.notNull(param, "参数格式错误");
            ServiceOrder order = param.getOrder();
            Assert.notNull(order, "订单不存在");
            List<OrderItem> items = order.getItems();
            logger.info("订单明细：" + JSON.toJSONString(items));
            Assert.notEmpty(items, "订单明细不存在");
            List<ElementModel> elements = param.getElements();
            // 申请人
            RequestContext context = param.getContext();
            Assert.notNull(context, "申请人不存在");
            // 位置
            LocationModel location = param.getLocation();
            // 配置信息
            JSONObject configs = param.getConfigs();
            // 资源归属信息
            configs.put("poolGroupId", location.getPoolGroupId());
            configs.put("businessId", location.getBusinessId());
            Long projectId = location.getProjectId();
            configs.put("projectId", projectId);
            configs.put("creatorId", location.getCreatorId());
            configs.put("ownerId", location.getOwnerId());
            configs.put("menderId", location.getMenderId());
            configs.put("remark",location.getRemark());
            String password = configs.getString("password");
            Long nameRuleId = configs.getLong("nameruleId");
            if (!StringUtils.isEmpty(password)) {
                Encryptor encryptor = new AESEncrptor();
                try {
                    password = encryptor.decrypt(password.trim(), null);
                    configs.put("password", password);
                } catch (Exception e) {
                    logger.error("Get error message:{}", e);
                    return new BocloudResult<>(false, e.getMessage());
                }
            }
            // 宿主机ID
            Long hostId = configs.getLong("hostId");

            // 订购信息
            EmptionModel emption = param.getEmption();
            // 使用时长信息
            DurationModel duration = emption.getDuration();
            // 使用时长单位Hour/Month
            DurationModel.Mode mode = duration.getMode();
            // 时长
            Integer month = duration.getAmount();
            // 申请个数
            Integer count = null == emption.getCount() ? 1 : emption.getCount();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            if (DurationModel.Mode.Hour == mode) {
                calendar.setTime(DateTools.stringToDateTime("2099-12-31 00:00:00"));
            } else {
                calendar.add(Calendar.MONTH, month);
            }
            CloudVendor vendor = cloudVendorRepository.query(location.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            CloudProvider provider = CloudProvider.valueOf(vendor.getType());

            if (CloudProvider.HUAWEI == provider){
                String instanceChargeType = "PostPaid";
                if (ChargeCommon.ChargeMode.PreCharge.equals(order.getChargeMode())){
                    // 预付费
                    instanceChargeType= "PrePaid";
                    Integer period = month;
                    String periodUnit = mode.name().toLowerCase();
                    configs.put("instanceChargeType",instanceChargeType);
                    configs.put("period",period);
                    configs.put("periodUnit",periodUnit);
                } else {
                    // 后付费
                    configs.put("instanceChargeType",instanceChargeType);
                }
            }

            // 通过调度策略分配的宿主机和存储
            String nsxNetworkName = null;
            List<JSONObject> targetObjs = new ArrayList<>();
            // 网卡端口组关联集合
            Long vpcId = configs.getLong("vpcId");
            if (CloudProvider.SMARTX == provider) {
                if (null != location.getPoolGroupId()) {
                    // 查询平台下所有主机
                    List<Server> allHosts = serverRepository.listByVendor(location.getVendorId());
                    // 查询资源池下面的主机
                    List<PoolGroupRelation> relationHosts = poolGroupRelationRepository.listByGroupId(location.getPoolGroupId());
                    relationHosts.removeIf(relation -> !relation.getEnabled());
                    relationHosts.removeIf(relation -> !"Host".equals(relation.getCategory()));
                    if (relationHosts.size() == allHosts.size()) {
                        // 如果资源池包含了平台下所有主机，则将serverId设置为0，利用smart-x的自身的自动调度放置云主机
                        configs.put("serverId", 0);
                    } else {
                        // 否则随便在资源池选择一个主机
                        configs.put("serverId", relationHosts.stream().findAny().get().getTarget());
                    }
                } else {
                    // 如果没有使用计算资源池，则将serverId设置为0，利用smart-x的自身的自动调度放置云主机
                    configs.put("serverId", 0);
                }
                configs.put("fullClone", false); // 默认快速克隆
                configs.put("status", "running"); // 默认创建完成自动开机
                configs.put("firmware", "BIOS"); // 默认引导选项为BIOS（另外一个是UEFI）

                if (configs.containsKey("networkCardConfigs")) {
                    JSONArray networkCardConfigs = configs.getJSONArray("networkCardConfigs");
                    List<NetcardOperation> netcardOperations = new ArrayList<>();
                    for (int i = 0; i < networkCardConfigs.size(); i++) {
                        JSONObject networkCardConfig = networkCardConfigs.getJSONObject(i);
                        String ip = Optional.of(networkCardConfig).map(o -> o.getJSONArray("address"))
                                .map(a -> a.toJavaList(String.class)).flatMap(a -> a.stream().findFirst())
                                .orElse(null);
                        String netmask = Optional.of(networkCardConfig).map(o -> o.getJSONArray("netmask"))
                                .map(a -> a.toJavaList(String.class)).flatMap(a -> a.stream().findFirst())
                                .orElse(null);

                        IpModel ipModel = new IpModel();
                        ipModel.setIp(ip);
                        ipModel.setMask(netmask);

                        Long portGroupId = networkCardConfig.getLong("portGroupId");
                        PortGroupRelation portGroupRelation = portGroupRelationRepository.query(portGroupId);
                        Assert.notNull(portGroupRelation, "未找到id为" + portGroupId + "的PortGroupRelation");
                        PortGroup portGroup = portGroupRepository.query(portGroupRelation.getPortGroupId());
                        Assert.notNull(portGroup, "未找到id为" + portGroupRelation.getPortGroupId() + "的PortGroup");
                        Network network = networkRepository.getByNetId(portGroup.getGroupVal());
                        Assert.notNull(network, "未找到uuid为" + portGroup.getGroupVal() + "的Network");

                        NetcardOperation netcardOperation = new NetcardOperation();
                        netcardOperation.setNetworkCardId(networkCardConfig.getLong("networkCardId"));
                        netcardOperation.setNetworkId(network.getId());
                        netcardOperation.setIpPolicy(networkCardConfig.getString("ipPolicy"));
                        netcardOperation.setIp(ipModel);
                        netcardOperations.add(netcardOperation);
                    }

                    configs.put("operations", netcardOperations);
                }
            }
            if (CloudProvider.OPENSTACK == provider || CloudProvider.EASYSTACK == provider) {
                OSTenant osTenant = osTenantRepository.getByTenantId(context.getTenant(), vendor.getId());
                Assert.notNull(osTenant, "租户云平台认证信息不存在");
            }
            if (CloudProvider.HUAWEI == provider) {
                OSTenant osTenant = osTenantRepository.getByTenantId(context.getTenant(), vendor.getId());
                if (null != osTenant) {
                    // 设置企业项目
                    configs.put("enterpriseProjectUuid", osTenant.getTenantUuid());
                }
            }
            if (CloudProvider.FUSIONSPHERE == provider) {
                //处理vdcId
                PoolGroup poolGroup = poolGroupRepository.query(location.getPoolGroupId());
                Assert.notNull(poolGroup, "资源池不存在");
                List<PoolGroupRelation> poolGroupRelations = poolGroupRelationRepository.listByGroupId(poolGroup.getId());
                if (ListTool.isEmpty(poolGroupRelations)) {
                    throw new Exception("没有资源池关联信息");
                }
                List<PoolGroupRelation> clusters = poolGroupRelations.stream().filter(poolGroupRelation -> poolGroupRelation.getCategory().equals("Cluster")).collect(Collectors.toList());
                List<PoolGroupRelation> storages = poolGroupRelations.stream().filter(poolGroupRelation -> poolGroupRelation.getCategory().equals("Storage")).collect(Collectors.toList());
                List<PoolGroupRelation> hosts = poolGroupRelations.stream().filter(poolGroupRelation -> poolGroupRelation.getCategory().equals("Host")).collect(Collectors.toList());
                if (ListTool.isEmpty(storages)) {
                    throw new Exception("此可用域下没有可用的数据存储，请更换可用域");
                }
                List<DataStore> dataStores = new ArrayList<>();
                for (PoolGroupRelation poolGroupRelation : storages) {
                    DataStore dataStore = dataStoreRepository.query(poolGroupRelation.getTarget());
                    dataStores.add(dataStore);
                }

                if ("Cluster".equalsIgnoreCase(poolGroup.getRelationType())) {
                    for (PoolGroupRelation poolGroupRelation : clusters) {
                        Cluster cluster = clusterRepository.query(poolGroupRelation.getTarget());
                        List<Server> servers = serverRepository.listByCluster(cluster.getId());
                        if (ListTool.isEmpty(servers)) {
                            continue;
                        }
                        if (null != configs.getLong("clusterId") && configs.getLong("clusterId") != 0) {
                            continue;
                        }
                        configs.put("clusterId", cluster.getId());
                        configs.put("vdcId", cluster.getVdcId());
                        configs.put("resourceLocation", "cluster");
                    }
                } else if ("Host".equalsIgnoreCase(poolGroup.getRelationType())) {
                    Server server = serverRepository.query(hosts.get(0).getTarget());
                    configs.put("vdcId", server.getVdcId());
                    configs.put("resourceLocation", "host");
                    configs.put("hostId", server.getId());
                }
                //处理硬盘
                List<VolumeModel> volumeModels = getFusionSphereVolumes(configs, dataStores);
                configs.put("diskDevices", volumeModels);
                //处理网卡
                List<NetworkCardModel> networkCardModels = getFusionSphereNetworkCard(configs);
                configs.put("networkCards", networkCardModels);
            }

            if (CloudProvider.VMWARE == provider || CloudProvider.FUSIONSPHERE == provider) {
                // 镜像id
                Long imageId = configs.getLong("imageId");
                if (null != imageId) {
                    Image targetImage = imageRepository.query(imageId);
                    Assert.notNull(targetImage, "未找到合适的镜像");
                    CloudServer template = cloudServerRepository.query(targetImage.getTemplateId());
                    Assert.notNull(template, "未找到合适的云主机模板");
                    configs.put("templateId", targetImage.getTemplateId());
                    templateName = template.getName();
                    templatePassword = template.receivePswd();
                }
            }

            if (CloudProvider.SANGFOR == provider) {
                String sourceVmId = configs.getString("sourceVmId");
                if (StringUtils.isNotEmpty(sourceVmId)) {
                    CloudServer template = cloudServerRepository.query(Long.valueOf(sourceVmId));
                    Assert.notNull(template, "源虚拟机不存在");
                    templateName = template.getName();
                    templatePassword = template.receivePswd();
                }
            }

            if (CloudProvider.VMWARE == provider) {
                BocloudResult<List<JSONObject>> bocloudResult = null;
                // 如果没有使用计算资源池，则默认按照随机策略分配宿主机和存储
                if (null != location.getPoolGroupId()) {
                    Map<String, Object> assignMap = Maps.newHashMap();
                    assignMap.put("Cpu", configs.getLong("cpu"));
                    assignMap.put("Memory", configs.getBigDecimal("memory"));
                    assignMap.put("Disk", configs.getLong("disk"));
                    assignMap.put("Instance", count);
                    assignMap.put("hostId", hostId);
                    // 根据计算资源池获取可分配宿主机，存储
                    bocloudResult = resSchedulerEngine.selectHost(location.getPoolGroupId(), "Cpu", assignMap,
                            configs.getString("diskCategory"));
                } else {
                    // nsx随机分配
                    bocloudResult =
                            resSchedulerEngine.byRandom(vendor.getId(), count, configs.getString("diskCategory"));
                    logger.info("nsx获取可分配宿主机");
                }
                Assert.isTrue(bocloudResult.isSuccess(), bocloudResult.getMessage());
                targetObjs = bocloudResult.getData();
                // 判断vcenter是否使用nsx网络
                if (null != vpcId) {
                    NsxTierOne tierOne = tierOneRepository.query(vpcId);
                    Assert.notNull(tierOne, "Tier1路由器不存在");
                    List<NsxSegment> segments = segmentRepository.listByConnectivityPath(tierOne.getPath());
                    for (NsxSegment segment : segments) {
                        nsxNetworkName = segment.getName();
                        BocloudResult<List<Ip>> achieveIpsData =
                                ipService.achieveNsxSegmentIps(segment.getId(), 1, "V4");
                        if (achieveIpsData.isFailed()) {
                            continue;
                        }
                        List<Ip> achieveIps = achieveIpsData.getData();
                        break;
                    }
                } else {
                    JSONArray ipConfigs =
                            Optional.ofNullable(configs.getJSONArray("networkCardConfigs")).orElse(new JSONArray());
                    for (int j = 0; j < ipConfigs.size(); j++) {
                        IpPool ipPool = null;
                        JSONObject config = ipConfigs.getJSONObject(j);
                        Long poolId = config.getLong("ipPoolId");
                        Long networkCardId = config.getLong("networkCardId");
                        Long portGroupId = config.getLong("portGroupId");
                        if (null != poolId && 0L != poolId) {
                            ipPool = ipPoolRepository.query(poolId);
                            Assert.notNull(ipPool, "IP池不存在");
                        }
                        if (configs.get("purpose") != null) {
                            config.put("index", j);
                        }
                        switch (config.getString("ipPolicy")) {
                            case "Dhcp":
                                BocloudResult<List<Ip>> dhcpIpResult =
                                        ipService.achieveDhcpIps(poolId, count.longValue(), ipPool.getVersion());
                                Assert.isTrue(dhcpIpResult.isSuccess(), dhcpIpResult.getMessage());
                                List<Ip> dhcpIps = dhcpIpResult.getData();
                                config.put("assignedIps", dhcpIps);
                                break;
                            case "Auto":
                                BocloudResult<List<Ip>> autoIpData =
                                        ipService.achievePoolIps(poolId, count.longValue(), ipPool.getVersion());
                                Assert.isTrue(autoIpData.isSuccess(), autoIpData.getMessage());
                                List<Ip> autoIps = autoIpData.getData();
                                config.put("assignedIps", autoIps);
                                break;
                            case "Manual":
                                List<String> addresses = JSONArray
                                        .parseArray(JSONObject.toJSONString(config.getJSONArray("address")), String.class);
                                List<Ip> manualIps = ipRepository.listIpsByPool(poolId, addresses);
                                Assert.notEmpty(manualIps, "未设置正确的IP地址");
                                config.put("assignedIps", manualIps);
                                break;
                            default:
                                break;
                        }
                    }
                    //更新网卡配置，后面需要用到，确保是同一个引用对象
                    configs.put("networkCardConfigs", ipConfigs);
                }
            }


            if (provider.equals(CloudProvider.SANGFOR) && "6.8".equals(vendor.getVersion())){
                //获取资源池Id
                Long poolGroupId = location.getPoolGroupId();
                List<PoolGroupRelation> hostRelations = poolGroupRelationRepository.list(poolGroupId, "Host");
                List<Server> servers = new ArrayList<>();
                for (PoolGroupRelation relation : hostRelations){
                    //获取server
                    Server server = serverRepository.query(relation.getTarget());
                    servers.add(server);
                }
                //筛选出符合条件的server
                Server server = servers.stream().min(Comparator.comparing(Server::getMemRatio)).orElse(null);
                configs.put("alwaysTryHost",server.getUuid());
            }

            // 为云主机名称准备数据
            Set<String> vmServerNameSet = new HashSet<>();

            // 数据预处理结果
            List<ProcessResult> processResults = new ArrayList<>();
            // 数据预处理
            List<JSONObject> processObjs = new ArrayList<>();
            JSONArray networkCardConfigs1 = configs.getJSONArray("networkCardConfigs");
            for (Object netWork : networkCardConfigs1){
                JSONObject jsonObject = (JSONObject) netWork;
                JSONArray address = jsonObject.getJSONArray("address");
                Long ipPoolId = jsonObject.getLong("ipPoolId");
                if (address.isEmpty()){
                    BocloudResult<List<Ip>> listBocloudResult = ipService.achievePoolIps(ipPoolId, count.longValue(), null);
                    List<String> ips = listBocloudResult.getData().stream().map(Ip::getIp).collect(Collectors.toList());
                    logger.info("打印分配到的ip:{}",JSON.toJSONString(ips));
                    address = JSONObject.parseArray(JSON.toJSONString(ips));
                    jsonObject.put("address",address);
                }
                logger.info("打印address:{}",JSON.toJSONString(address));
            }
            for (int i = 0; i < count; i++) {
                JSONObject newObj = JSONObject.parseObject(configs.toJSONString());
                logger.info("打印newObj:{}",JSON.toJSONString(newObj));
                if (null != nameRuleId && 0L != nameRuleId) {
                    String serverName = serverOperationHelper.generateName(nameRuleId, vendor.getId(), projectId, context);
                    newObj.put("name", serverName);
                } else {
                    if (CloudProvider.AZURE == provider) {
                        String oldServerName = configs.getString("name");
                        newObj.put("name", oldServerName + "-" + IDFactory.instance().mac());
                        newObj.put("systemDiskName", oldServerName + "-" + IDFactory.instance().mac());
                        //在数据预处理的情况下 创建静态ip并插入到云主机中
                    } else if (CloudProvider.SANGFOR == provider){
                        //获取用途
                        String purpose = newObj.getString("purpose");
                        if (newObj.get("purpose") != null) {
                            JSONArray networkCardConfigs = newObj.getJSONArray("networkCardConfigs");
                            for (Object object : networkCardConfigs) {
                                JSONObject jsonObject = (JSONObject) object;
                                BocloudResult<User> userDetail = smsUserService.detail(location.getCreatorId());
                                newObj.put("name", jsonObject.getJSONArray("address").get(i) +"-"+ userDetail.getData().getName() +"-"+purpose);
                                break;
                            }
                        }
                    }else {

                        // newObj.put("name", configs.getString("name") + "_" + IDFactory.instance().mac());
                        // 如果自服务指定云主机名称前缀，先看看【云主机名称前缀】是否可以作为名称，否则增加数字后缀 sxp:2023.6.6
                        String serverName = configs.getString("name");
                        String newServerName = getValidVmName(vmServerNameSet, vendor, serverName, i + 1, count);
                        newObj.put("name", newServerName);
                    }
                }

                //深信服处理资源池分组
                if (provider.equals(CloudProvider.SANGFOR)){
                    //查询资源池获取绑定的分组
                    PoolGroup poolGroup = poolGroupRepository.query(location.getPoolGroupId());
                    Assert.notNull(poolGroup,"资源池不存在");
                    //获取分组信息
                    SangforServerGroup sangforServerGroup = serverGroupRepository.listById(poolGroup.getGroupId());
                    Assert.notNull(sangforServerGroup,"分组不存在请检查");
                    newObj.put("groupUuid",sangforServerGroup.getUuid());
                    JSONArray array1 = new JSONArray();
                    JSONArray networkCardConfigs = newObj.getJSONArray("networkCardConfigs");
                    for (int j = 0; j < networkCardConfigs.size(); j++) {
                        JSONObject netWorkObject = (JSONObject) networkCardConfigs.get(j);
                        JSONArray address = netWorkObject.getJSONArray("address");
                        Long ipPoolId = netWorkObject.getLong("ipPoolId");
                        logger.info("打印address:{}",JSON.toJSONString(address));
                        PortGroupRelation portGroupRelation = portGroupRelationRepository.listByIpPoolId(ipPoolId);
                        logger.info("打印portGroupRelation：{}",JSON.toJSONString(portGroupRelation));
                        //获取端口组id
                        SangforVlanGroup vlanGroup = sangforVlanGroupRepositpry.query(portGroupRelation.getPortGroupId());
                        //获取对应网卡信息
                        Network network = networkRepository.getByNetId(vlanGroup.getNetworkUuid());

                        JSONObject object = new JSONObject();
                        object.put("ip",address.get(i));
                        object.put("mac",networkService.listMac(vendor.getId()).getData().toString());
                        object.put("bvsId",vlanGroup.getNetworkUuid());
                        object.put("vifId","net"+j);
                        object.put("connect",1);
                        object.put("bridgename",network.getName());
                        object.put("portUuid",vlanGroup.getUuid());
                        object.put("mask",cidrToSubnetMask(portGroupRelation.getCidr()));
                        object.put("gateway",portGroupRelation.getGateWay());
                        array1.add(object);
                    }
                    newObj.put("newWorkConfigs",array1);
                }


                if (!ListTool.isEmpty(targetObjs)) {
                    JSONObject targetObj = targetObjs.get(i);
                    if (hostId != null && hostId.longValue() > 0L) {
                        if (!Objects.equals(hostId, targetObj.getLong("hostId"))) {
                            return new BocloudResult<>(false, "筛选后的宿主机不是指定的宿主机，请检查宿主机的CPU、内存资源是否还有剩余");
                        }
                    }
                    newObj.put("storeId", targetObj.getLong("storeId"));
                    newObj.put("hostId", targetObj.getLong("hostId"));
                    // 数据盘分配存储
                    if (newObj.containsKey("addDiskList")) {
                        List<JSONObject> addDiskList =
                                JSONArray.parseArray(newObj.getString("addDiskList"), JSONObject.class);
                        if (!ListTool.isEmpty(addDiskList)) {
//                            List<String> dataStoreNames = resSchedulerEngine.assignStore(targetObj.getLong("hostId"), addDiskList);
                            List<String> dataStoreNames = resSchedulerEngine.assignStore(location.getPoolGroupId(), targetObj.getLong("hostId"), addDiskList);
                            if (ListTool.isEmpty(dataStoreNames)) {
                                return new BocloudResult<>(false, "为云主机分配数据盘存储发生错误");
                            }
                            newObj.put("dataStoreNames", dataStoreNames);
                            List<Integer> disks = new ArrayList<>();
                            for (JSONObject dataDisk : addDiskList) {
                                Integer disk = dataDisk.getInteger("disk");
                                disks.add(disk);
                            }
                            newObj.put("disks", disks);
                        }
                        newObj.put("dataDiskList", newObj.getString("addDiskList"));
                        newObj.remove("addDiskList");
                    }
                }
                processObjs.add(newObj);
            }
            if (CloudProvider.SANGFOR == provider && processObjs.size() > 0 && "6.8".equals(vendor.getVersion())) {
                JSONObject jsonObject = processObjs.get(0);
                String ipList = jsonObject.getString("ip");
                List<CloudServer> cloudServers = cloudServerRepository.listByVid(vendor.getId());
                BocloudResult bclResult = CloudServerServiceImpl.checkIpRepeat(cloudServers, ipList, RequestContext.Catalog.Account);
                if (bclResult.isFailed()){
                    return bclResult;
                }
            }

            int size = processObjs.size();
            for (int indexInSpec = 0; indexInSpec < size; indexInSpec++) {
                JSONObject object = processObjs.get(indexInSpec);
                object.put("expiredTime", calendar.getTime());
                BocloudResult<ServerBuilder> builderResult =
                        serverOperationHelper.getProcess(provider, vendor, context);
                if (builderResult.isFailed()) {
                    continue;
                }
                ServerBuilder process = builderResult.getData();
                BocloudResult<ProcessResult> result = null;
                if (CloudProvider.VMWARE == provider) {
                    JSONArray networkCardConfigs = configs.getJSONArray("networkCardConfigs");
                    List<Ip> assignedIps = new ArrayList<>();
                    for (int i = 0; i < networkCardConfigs.size(); i++) {
                        JSONObject ipConfig = networkCardConfigs.getJSONObject(i);
                        //确保，上面分配过了的ip
                        List<Ip> ips = (List<Ip>) ipConfig.get("assignedIps");
                        assignedIps.add(ips.get(indexInSpec));
                    }
//                    Map<Long, Ip> ipMap = new HashMap<>();
//                    for (Map.Entry<Long, List<Ip>> entry : networkConfigs.entrySet()) {
//                        Long networkCardId = entry.getKey();
//                        List<Ip> ips = entry.getValue();
//                        Ip ip = ips.get(indexInSpec);
//                        ipMap.put(networkCardId, ip);
//                    }
                    result = serverOperationHelper.prepareVcenter(object, param.getContext(), vendor, process, assignedIps,
                            nsxNetworkName);
                } else if (CloudProvider.AZURE == provider) {
                    result = serverOperationHelper.prepare(JSONObject.parseObject(object.toJSONString(), VmGenericParam.class), param.getContext(), vendor, process);
                } else if (CloudProvider.SANGFOR == provider){
                    result = serverOperationHelper.prepareSangfor(object, param.getContext(), vendor, process, indexInSpec, size);
                } else {
                    result = serverOperationHelper.prepare(
                            JSONObject.parseObject(object.toJSONString(), VmGenericParam.class), param.getContext(), vendor,
                            process);
                }
                Assert.isTrue(result.isSuccess(), result.getMessage());
                result.getData().setServerBuilder(process);
                processResults.add(result.getData());
            }

            final String finalTemplateName = templateName;
            final String finalPassword = password;
            final String finalTemplatePassword = templatePassword;
            // 配额
            List<QuotaBean> quotas = param.getQuotas();
            taskExecutor.execute(() -> {
                logger.info("Apply virtual machine start...");
                // 创建成功的云主机
                List<BocloudResult> succList = new ArrayList<>();
                // 创建失败的云主机
                List<BocloudResult> failList = new ArrayList<>();
                List<Future<BocloudResult<CloudServer>>> futures = new ArrayList<>();
                try {
                    // 执行创建云主机的操作
                    for (ProcessResult result : processResults) {
                        if (CloudProvider.SMARTX == provider) {
                            result.getCloudServer().setRegion(location.getRegion());
                            result.getCloudServer().setRegionId(location.getRegion());
                        }
                        futures.add(
                                taskExecutor.submit(() -> serverOperationHelper.builder(vendor.getType(), vendor.getId(),
                                        result.getCloudServer(), context, result.getServerBuilder(), param.getCallback())));
                        if (CloudProvider.SANGFOR == provider) {
                            // 深信服克隆虚拟机时，如果短时间内发送多次请求，只有一次请求能成功  sxp:2023.3.27
                            TimeUnit.MINUTES.sleep(1);
                        }
                    }
                    Map<String, List<OrderItem>> orderItemMap = new HashedMap();
                    List<OrderItem> list = null;
                    for (OrderItem orderItem : items) {
                        String serviceCode = orderItem.getServiceCode();
                        if (orderItemMap.containsKey(serviceCode)) {
                            list = orderItemMap.get(serviceCode);
                        } else {
                            list = new ArrayList<>();
                        }
                        list.add(orderItem);
                        orderItemMap.put(serviceCode, list);
                    }
                    String vmServiceCode = vendor.getType().toLowerCase() + ".standard.server";

                    // 是否开启OA消息
                    boolean oaEnable = zjkyOAService.getOaEnable();

                    String cloudServiceName = null;
                    User creatorUser = null;
                    List<User> managerUserList = null;
                    if (oaEnable) {
                        // 云主机类型
                        CloudService cloudService = cosInternalService.detailService(vmServiceCode);
                        if (cloudService != null) {
                            //logger.info("cloudService:" + JSON.toJSONString(cloudService));
                            cloudServiceName = cloudService.getName();
                        } else {
                            logger.info("cloudService is null, query params is: " + vmServiceCode);
                            cloudServiceName = provider.name() + "云主机";
                        }
                        // 申请人
                        Long creatorId = location.getCreatorId();
                        BocloudResult<User> userResult;
                        if (creatorId != null && creatorId.longValue() > 0L) {
                            userResult = smsUserService.detail(creatorId);
                            if (userResult.isSuccess()) {
                                creatorUser = userResult.getData();
                            }
                        }
                        // 管理员
                        Long roleId = 1L;// 角色为超级管理员
                        List<Param> params = new ArrayList<>();
                        params.add(new Param(MapTools.simpleMap("status", "NORMAL"), Sign.EQ));
                        userResult = smsUserService.listUsers(roleId, new Pager(1, Integer.MAX_VALUE, params, null));
                        if (userResult.isSuccess()) {
                            JSONObject json = JSON.parseObject(String.valueOf(userResult.getData()), JSONObject.class);
                            managerUserList = json.getJSONArray(Common.ROWS).toJavaList(User.class);
                        }
                    }
                    StringBuilder vmSb = new StringBuilder();

                    // 获取线程池返回结果
                    for (int i = 0; i < futures.size(); i++) {
                        List<ResourceModel> resources = new ArrayList<>();
                        // 通知订单
                        OrderMessage message = null;
                        List<OrderItem> vmOrderItems = orderItemMap.get(vmServiceCode);
                        if (ListTool.isEmpty(vmOrderItems)) {
                            continue;
                        }
                        OrderItem item = vmOrderItems.get(0);
                        vmOrderItems.remove(item);
                        orderItemMap.put(vmServiceCode, vmOrderItems);

                        BocloudResult<CloudServer> result = futures.get(i).get();
                        CloudServer cloudServer = result.getData();
                        if (result.isSuccess()) {
                            ObjectRelation relation = new ObjectRelation(context.getTarget(), cloudServer.getId(),
                                    false, ResourceCategory.Computer.name(), context.getCatalog().name(), 0);
                            relation.setExpiredTime(calendar.getTime());
                            objectRelationRepository.save(relation);
                            cloudServer.setUuid(item.getSn());
                            logger.info("云主机名称：{}，sn：{}", cloudServer.getName(), cloudServer.getUuid());
                            cloudServer.setGmtModify(new Date());
                            cloudServer.setExpiredTime(calendar.getTime());
                            cloudServer.setCategoryId(configs.getLong("categoryId"));
                            cloudServer.setSkuId(item.getSkuId());
                            String locationRegion = location.getRegion();
                            Long poolGroupId = location.getPoolGroupId();
                            // 如果区域为空 则从资源池获取区域信息
                            if(StringUtils.isEmpty(locationRegion) && null != poolGroupId) {
                            	PoolGroup poolGroup = poolGroupRepository.query(poolGroupId);
                            	if(null != poolGroup) {
                            		location.setRegion(poolGroup.getRegion());
                            	}
                            }
                            // 存地域，可用域数据
                            cloudServer.setProps(JSONObject.toJSONString(location));
                            // 标签
                            String resourceLabel = configs.getString("resourceLabel");
                            cloudServer.setResourceLabel(resourceLabel);
                            cloudServerRepository.update(cloudServer);
                            //发送消息给cop
                            resourceTaskNotice.sendLogicalMessage(cloudServer, ResourceTaskNotice.Action.UPDATE);

                            // 云主机名称和IP地址
                            if (oaEnable) {
                                vmSb.append(cloudServer.getName()).append('(').append(cloudServer.getManagerIp()).append(")、");
                            }

                            if (CloudProvider.AWS.name().equalsIgnoreCase(vendor.getType())) {
                                try {
                                    if (configs.getBoolean("hasIpv6")) {
                                        JSONArray privateIps = JSONArray.parseArray(cloudServer.getPrivateIps());
                                        Subnet subnet = subnetRepository.query(configs.getLong("subnetId"));
                                        String ipv6Cidr = subnet.getIpv6Cidr();
                                        logger.info("ipv6Cidr:" + ipv6Cidr);
                                        List<NetworkInterface> interfaces = networkInterfaceRepository.listByServerId(vendor.getId(),
                                                cloudServer.getId());
                                        if (ListTool.isEmpty(interfaces)) {
                                            logger.error("云主机网络接口不存在");
                                            resourceEventPublisher.send(new OperateResult(false, "云主机网络接口不存在",
                                                    vendor.getType().toLowerCase() + ".vm",
                                                    MapTools.simpleMap(Common.VENDORID, vendor.getId()), 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(vendor.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设置失败", vendor.getType().toLowerCase() + ".vm",
                                                        MapTools.simpleMap(Common.VENDORID, vendor.getId()), 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设置失败", vendor.getType().toLowerCase() + ".vm",
                                                    MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                                }
                                try {
                                    if (configs.getBoolean("hasEip")) {
                                        Long eipId = configs.getLong("eipId");
                                        ElasticIp elasticIp = null;
                                        if (eipId == null) {
                                            ElasticIp elasticIpInfo = new ElasticIp();
                                            elasticIpInfo.setName("EIP_" + UUID.randomUUID());
                                            elasticIpInfo.setVendorId(vendor.getId());
                                            elasticIpInfo.setRegionId(configs.getString("regionId"));
                                            BocloudResult allocateResult = elasticIpService.allocate(elasticIpInfo, context);
                                            if (allocateResult.isFailed()) {
                                                logger.error("EIP分配失败 {} ", allocateResult.getMessage());
                                                resourceEventPublisher.send(new OperateResult(allocateResult.isSuccess(),
                                                        "EIP分配失败", vendor.getType().toLowerCase() + ".vm",
                                                        MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory,
                                                        context));
                                            } else {
                                                elasticIp = (ElasticIp) allocateResult.getData();
                                            }
                                        } else {
                                            elasticIp = elasticIpRepository.query(eipId);
                                        }
                                        if (null == elasticIp) {
                                            logger.error("EIP数据不存在");
                                            resourceEventPublisher.send(new OperateResult(false, "EIP数据不存在",
                                                    vendor.getType().toLowerCase() + ".vm",
                                                    MapTools.simpleMap(Common.VENDORID, vendor.getId()), 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失败", vendor.getType().toLowerCase() + ".vm",
                                                        MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory,
                                                        context));
                                            }

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

                            // 查询磁盘设备列表
                            List<Volume> volumes;
                            if (CloudProvider.SMARTX.name().equals(vendor.getType())) {
                                volumes = volumeRepository.listVolumeByServerId(cloudServer.getId());
                            } else {
                                volumes = volumeRepository.listByServerId(cloudServer.getId());
                            }
                            // 数据盘 + 系统盘
                            if (!ListTool.isEmpty(volumes)) {
                                String volumeServiceCode;
                                if ("VMWARE".equals(vendor.getType()) ||
                                        CloudProvider.SANGFOR.name().equals(vendor.getType())) {
                                    volumeServiceCode = vendor.getType().toLowerCase() + ".storage.disk";
                                } else {
                                    volumeServiceCode = vendor.getType().toLowerCase() + ".standard.volume";
                                }
                                for (Volume volume : volumes) {
                                    String uuid = null;
                                    Long skuId = null;
                                    Long categotryId = null;
                                    OrderItem orderItemValue = null;
                                    List<OrderItem> volumeOrderItems = orderItemMap.get(volumeServiceCode);
                                    if (!ListTool.isEmpty(volumeOrderItems)) {
                                        for (OrderItem orderItem : volumeOrderItems) {
                                            List<ElementModel> elementModels =
                                                    JSON.parseArray(orderItem.getElements(), ElementModel.class);
                                            if (!ListTool.isEmpty(elementModels)) {
                                                ElementModel elementModel = elementModels.get(0);
                                                List<SpecModel> specs = elementModel.getSpecs();
                                                if (!ListTool.isEmpty(specs)) {
                                                    SpecModel specModel = specs.get(0);
                                                    if (null != specModel
                                                            && specModel.getDisk().equals(volume.getSize())) {
                                                        orderItemValue = orderItem;
                                                        categotryId = elementModel.getCategoryId();
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                        // 后续需要加上过滤
                                        if (null != orderItemValue) {
                                            uuid = orderItemValue.getSn();
                                            skuId = orderItemValue.getSkuId();
                                            volume.setUuid(uuid);
                                            volume.setSkuId(skuId);
                                            volume.setCategoryId(categotryId);
                                            volumeOrderItems.remove(orderItemValue);
                                            orderItemMap.put(volumeServiceCode, volumeOrderItems);
                                        }
                                    }
                                    volume.setExpiredTime(cloudServer.getExpiredTime());
                                    volume.setMenderId(cloudServer.getMenderId());
                                    volume.setTenantId(cloudServer.getTenantId());
                                    volume.setProjectId(cloudServer.getProjectId());
                                    volume.setBusinessId(cloudServer.getBusinessId());
                                    volume.setOwnerId(cloudServer.getOwnerId());
                                    volume.setCreatorId(cloudServer.getCreatorId());
                                    volume.setSkuId(skuId);
                                    volume.setCategoryId(categotryId);
                                    volumeRepository.update(volume);
                                    List<ResourceModel> volumeResources = new ArrayList<>();
                                    if (null != orderItemValue && !StringUtils.isEmpty(orderItemValue.getServiceCode())) {
                                        volumeResources.add(new ResourceModel(volume.getName(), volume.getVolumeUuid(),
                                                orderItemValue.getServiceCode(), volume.getVolumeUuid(), volume.getUuid()));
                                    }
                                    if (result.getMessage().contains("创建LVM发生错误")) {
                                        message = new OrderMessage(uuid, Operation.Application,
                                                OrderItemStatus.OpenedSuccess, null, result.getMessage(), cloudServer.getGmtCreate(),
                                                calendar.getTime(), volumeResources, ResourceCategory.Storage.name(), context);
                                    } else {
                                        message = new OrderMessage(uuid, Operation.Application,
                                                OrderItemStatus.OpenedSuccess, null, "云主机硬盘申请成功", cloudServer.getGmtCreate(),
                                                calendar.getTime(), volumeResources, ResourceCategory.Storage.name(), context);
                                    }
                                    message.setCategory(ResourceCategory.Storage.name());
                                    // 通知订单
                                    logger.info("结果消息发送 ： " + JSON.toJSONString(message));
                                    amqpTemplate.convertAndSend("resource.result.queue", message);
                                }
                            }
                            BocloudResult bocloudResult = new BocloudResult<>(true,
                                    "【" + cloudServer.getName() + "】创建成功【" + result.getMessage() + "】");
                            succList.add(bocloudResult);
                            resources.add(new ResourceModel(cloudServer.getName(), cloudServer.getInstanceId(),
                                    param.getService(), cloudServer.getInstanceId(), cloudServer.getUuid()));
                            logger.info("item.getSn()：{}", item.getSn());
                            message = new OrderMessage(item.getSn(), Operation.Application,
                                    OrderItemStatus.OpenedSuccess, null, "云主机申请创建成功", cloudServer.getGmtCreate(),
                                    calendar.getTime(), resources, ResourceCategory.Computer.name(), context);
                            message.setCategory(ResourceCategory.Computer.name());
                            // 通知订单
                            logger.info("结果消息发送 ： " + JSON.toJSONString(message));
                            amqpTemplate.convertAndSend("resource.result.queue", message);
                        } else {
                            // 磁盘失败回调
                            String volumeServiceCode;
                            if ("VMWARE".equals(vendor.getType())) {
                                volumeServiceCode = vendor.getType().toLowerCase() + ".storage.disk";
                            } else {
                                volumeServiceCode = vendor.getType().toLowerCase() + ".standard.volume";
                            }
                            List<OrderItem> volumeOrderItems = orderItemMap.get(volumeServiceCode);
                            for (OrderItem volumeOrderItem : volumeOrderItems) {
                                OrderMessage volumeMessage =
                                        new OrderMessage(volumeOrderItem.getSn(), Operation.Application,
                                                OrderItemStatus.OpenedFailure, null, "创建失败【" + result.getMessage() + "】", null,
                                                null, new ArrayList<>(), ResourceCategory.Computer.name(), context);
                                // 通知订单
                                logger.info("结果消息发送 ： " + JSON.toJSONString(volumeMessage));
                                amqpTemplate.convertAndSend("resource.result.queue", volumeMessage);
                            }
                            if (cloudServer != null) {
                                // 如果云主机存在直接删除
                                cloudServerRepository.remove(cloudServer.getId(), context.getTarget());
                                //通知主机资源
                                resourceTaskNotice.sendLogicalMessage(cloudServer, ResourceTaskNotice.Action.DEL);
                            }
                            BocloudResult bocloudResult =
                                    new BocloudResult<>(false, "创建失败【" + result.getMessage() + "】");
//                            applyVmFailCallback(item.getSn(), bocloudResult, context, quotas, items.size());
                            failList.add(bocloudResult);
                        }
                    }

                    // 资源创建完成后将办结信息推送给管理员和申请人，并且管理员可查看密码信息 sxp:2023.8.29
                    // 消息格式：XXX提交的云资源【xxx云主机】申请已经办结。创建成功的云主机为：xxx云主机名称1(IP地址1)、
                    // xxx云主机名称2(IP地址2)。
                    // （管理员追加密码信息:云主机的密码为xxxxxx）
                    // （如果密码为空，则密码信息改为：云主机的密码和模板xxx的密码相同）
                    if (oaEnable && vmSb.length() > 0 && creatorUser != null) {
                        vmSb.setLength(vmSb.length() - 1);
                        String creatorName = creatorUser.getName();
                        String subject = creatorName + "提交的云资源【" + cloudServiceName + "】申请已经办结。创建成功的云主机为:"
                                + vmSb.toString() + "。云主机所属的云平台名称为：" + vendor.getName() + "。";
                        logger.info(subject);
                        // 发给申请人
                        sendOaMessage(subject, creatorUser);
                        // 发给管理员
                        if (managerUserList != null && !managerUserList.isEmpty()) {
                            if (StringUtils.isNotEmpty(finalPassword)) {
                                subject = subject + "云主机的密码为:" + finalPassword + "。";
                            } else if (StringUtils.isNotEmpty(finalTemplatePassword)) {
                                subject = subject + "云主机的密码为:" + finalTemplatePassword + "。";
                            } else {
                                String tempName = new String(finalTemplateName.toCharArray());
                                if (StringUtils.isNotEmpty(tempName)) {
                                    tempName = "[" + tempName + "]";
                                } else {
                                    tempName = "";
                                }
                                subject = subject + "云主机的密码和镜像模板" + tempName + "的密码相同。";
                            }
                            for (User managerUser : managerUserList) {
                                sendOaMessage(subject, managerUser);
                            }
                        }
                    }
                } catch (Exception e) {
                    logger.error("apply virtual machine fail:", e);
                }
                // 发送给云平台统计队列对云平台重新统计
                JSONObject jsonObject = new JSONObject();
                jsonObject.put(Common.VENDORID, vendor.getId());
                amqpTemplate.convertAndSend("vendor.statistics.queue", jsonObject);
                logger.info("Apply virtual machine end");
            });
            return new BocloudResult<>(true, "申请任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("Apply virtual machine error", e);
            return new BocloudResult<>(false, "申请云主机失败：" + e.getMessage());
        }
    }


    public String cidrToSubnetMask(String cidr) throws Exception {
        Pattern pattern = Pattern.compile("(\\d+\\.\\d+\\.\\d+\\.\\d+)/(\\d+)");
        Matcher matcher = pattern.matcher(cidr);

        if (matcher.matches()) {
            String ipAddress = matcher.group(1);
            int prefixLength = Integer.parseInt(matcher.group(2));

            int mask = 0xFFFFFFFF << (32 - prefixLength);

            byte[] bytes = new byte[]{
                    (byte) (mask >>> 24 & 0xFF),
                    (byte) (mask >>> 16 & 0xFF),
                    (byte) (mask >>> 8 & 0xFF),
                    (byte) (mask & 0xFF)
            };

            InetAddress inetAddress = InetAddress.getByAddress(ipAddress, bytes);

            return inetAddress.getHostAddress();
        } else {
            throw new IllegalArgumentException("Invalid CIDR format");
        }
    }

    /**
     * 发送OA待办消息
     *
     * @author sxp
     * @since 2023/8/29
     */
    private void sendOaMessage(String subject, User user) {
        try {
            String createTime = DateUtils.dateToString(DateUtils.getTodayTime(), DateUtils.STANDARD_DATETIME_FORMAT);

            // OA待办信息
            OaMessageBean oaMessageBean = new OaMessageBean();
            oaMessageBean.setModelId(UUID.randomUUID().toString());

            if (subject.length() <= 256) {
                oaMessageBean.setSubject(subject);
            } else {
                oaMessageBean.setSubject(subject.substring(0, 256));
            }
            oaMessageBean.setLink(ZjkyHelper.getSsoLink());
            oaMessageBean.setMobileLink(ZjkyHelper.getSsoLink());
            oaMessageBean.setPadLink(ZjkyHelper.getSsoLink());

            if (user != null) {
                String targets = String.format("{\"PersonNo\":\"%s\"}", user.getAccount());
                oaMessageBean.setTargets(targets);
            } else {
                logger.warn("未获取到用户信息，本条待办消息不发送");
                return;
            }
            oaMessageBean.setCreateTime(createTime);

            JSONObject params = JSON.parseObject(JSON.toJSONString(oaMessageBean));

            BocloudResult<OaNotifyTodoAppResult> oaResult = zjkyOAService.sendTodo(params);
            if (oaResult.isFailed()) {
                logger.info("发送待办消息失败，返回结果为{}，消息内容为{}", oaResult.getMessage(), params.toJSONString());
                return;
            }

            OaNotifyTodoAppResult appResult = oaResult.getData();
            logger.info("发送待办消息成功，返回结果为{}", JSON.toJSONString(appResult));
        } catch (Exception e) {
            logger.error("发送OA待办消息失败：" + e.getMessage(), e);
        }
    }

    /**
     * 获取未使用的虚拟机名称
     *
     * @author sxp
     * @since 2022/8/29
     */
    private String getValidVmName(Set<String> vmNameSet, CloudVendor vendor, String vmName, int startSn, int count) {
        boolean exists = false;

        if (count == 1) {
            if (!vmNameSet.contains(vmName)) {
                exists = cloudServerRepository.exists(vmName, vendor.getId());
            } else {
                exists = true;
            }
            if (!exists) {
                vmNameSet.add(vmName);
                return vmName;
            }
        }

        int MAX_TRY = 20;
        String newVmName = vmName;

        for (int i = 0; i < MAX_TRY; i++) {
            newVmName = vmName + "_" + (startSn + i);
            if (vmNameSet.contains(newVmName)) {
                continue;
            }
            exists = cloudServerRepository.exists(newVmName, vendor.getId());
            if (!exists) {
                break;
            }
        }
        if (!exists) {
            vmNameSet.add(newVmName);
            return newVmName;
        }

        newVmName = vmName + "_" + IDFactory.instance().mac();
        vmNameSet.add(newVmName);
        return newVmName;
    }

    private List<NetworkCardModel> getFusionSphereNetworkCard(JSONObject configs) throws Exception {
        List<NetworkCardModel> networkCardModels = new ArrayList<>();
        List<JSONObject> networkCardConfigs = JSONArray.parseArray(JSONObject.toJSONString(configs.get("networkCardConfigs")), JSONObject.class);
        if (ListTool.isEmpty(networkCardConfigs)) {
            throw new Exception("没有选择网卡信息，请重新选择");
        }
        for (int i = 1; i <= networkCardConfigs.size(); i++) {
            JSONObject json = networkCardConfigs.get(i - 1);
            NetworkCardModel model = new NetworkCardModel();
            model.setEnableSecurityGroup(json.getBoolean("enableSecurityGroup"));
            model.setQueues(json.getInteger("queues"));
            model.setSecurityGroupUuid(json.getString("securityGroupUuid"));
            model.setSequenceNum(i);
            model.setType(json.getString("type"));
            model.setVringbuf(json.getInteger("vringbuf"));
            PortGroup portGroup = portGroupRepository.query(json.getLong("portGroupId"));
            Assert.notNull(portGroup, "端口组不存在");
            model.setPortGroupUuid(portGroup.getGroupVal());
            networkCardModels.add(model);
        }
        return networkCardModels;
    }

    private List<VolumeModel> getFusionSphereVolumes(JSONObject configs, List<DataStore> dataStores) throws Exception {
        List<VolumeModel> volumeModels = new ArrayList<>();
        // 系统盘
        VolumeModel volumeModel = getSystemVolumeModel(configs, 1, true);
        // 选择数据存储
        List<DataStore> dataStoreList = dataStores.stream().filter(dataStore -> dataStore.getFreeSpace() > volumeModel.getSize()).collect(Collectors.toList());
        if (ListTool.isEmpty(dataStoreList)) {
            throw new Exception("此可用域下数据存储可用不足，请更换可用域");
        }
        volumeModel.setDataStoreUuid(dataStoreList.get(0).getStoreVal());
        volumeModels.add(volumeModel);
        // 处理数据盘
        List<DataStore> filterStores;
        List<JSONObject> addDisks = JSONArray.parseArray(JSONObject.toJSONString(configs.get("addDiskList")), JSONObject.class);
        if (!ListTool.isEmpty(addDisks)) {
            for (int i = 1; i <= addDisks.size(); i++) {
                JSONObject json = addDisks.get(i - 1);
                VolumeModel dataVolumeModel = getDataVolumeModel(json, false);
                filterStores = dataStores.stream().filter(dataStore -> dataStore.getFreeSpace() > dataVolumeModel.getSize()).collect(Collectors.toList());
                if (ListTool.isEmpty(filterStores)) {
                    throw new Exception("此可用域下数据存储可用不足，请更换可用域");
                }
                dataVolumeModel.setDataStoreUuid(filterStores.get(0).getStoreVal());
                volumeModels.add(dataVolumeModel);
            }
        }
        return volumeModels;
    }

    /**
     * FusionSphere系统盘配置
     */
    private VolumeModel getSystemVolumeModel(JSONObject configs, int seqNo, boolean bootVolumn) {
        VolumeModel volumeModel = new VolumeModel();
        volumeModel.setPciType("VIRTIO");
        volumeModel.setSequenceNum(seqNo);
        volumeModel.setBootVolume(bootVolumn);
        volumeModel.setVolumeType(configs.getString("diskType"));
        if ("2".equals(volumeModel.getVolumeType())) {
            //精简模式
            volumeModel.setThinlyProvisioned(true);
        }

        JSONObject category = configs.getJSONObject("diskCategory");
        volumeModel.setPersistentDisk(category.getBoolean("persistentDisk"));
        volumeModel.setIndepDisk(category.getBoolean("indepDisk"));
        volumeModel.setSize(Integer.valueOf(configs.getString("disk")));
        return volumeModel;
    }

    /**
     * FusionSphere数据盘配置
     */
    private VolumeModel getDataVolumeModel(JSONObject json, boolean bootVolumn) {
        //"size": 11,
        //"sequenceNum": "2",
        //"indepDisk": false,
        //"persistentDisk": true,
        //"pciType": "VIRTIO",
        //"volumeType": "1"
        VolumeModel volumeModel = new VolumeModel();
        volumeModel.setPciType(json.getString("pciType"));
        volumeModel.setSequenceNum(json.getIntValue("sequenceNum"));
        volumeModel.setBootVolume(bootVolumn);
        volumeModel.setVolumeType(json.getString("volumeType"));
        if ("2".equals(volumeModel.getVolumeType())) {
            //精简模式
            volumeModel.setThinlyProvisioned(true);
        }

        volumeModel.setPersistentDisk(json.getBooleanValue("persistentDisk"));
        volumeModel.setIndepDisk(json.getBooleanValue("indepDisk"));
        volumeModel.setSize(json.getIntValue("size"));
        return volumeModel;
    }

    public void applyVmFailCallback(String sn, BocloudResult bocloudResult, RequestContext context,
                                    List<QuotaBean> quotas, int itemSize) {
        try {
            quotas = Optional.ofNullable(quotas).orElse(new ArrayList<>());
            OrderMessage message = new OrderMessage(sn, Operation.Application, OrderItemStatus.OpenedFailure, null,
                    bocloudResult.getMessage(), null, null, new ArrayList<>(), ResourceCategory.Computer.name(), context);
            // 回滚配额
            List<QuotaBean> beans = new ArrayList<>();
            for (QuotaBean bean : quotas) {
                beans.add(new QuotaBean(bean.getCode(), bean.getValue() / itemSize));
            }
            message.setQuotas(beans);
            message.setCategory(ResourceCategory.Computer.name());
            // 通知订单
            logger.info("结果消息发送 ： " + JSON.toJSONString(message));
            amqpTemplate.convertAndSend("resource.result.queue", message);
        } catch (AmqpException e) {
            logger.error("申请云主机回滚配额失败：" + e.getMessage());
        }
    }

    @Override
    public BocloudResult recycle(Long id, RequestContext context) {
        try {
            CloudServer server = cloudServerRepository.get(id);
            Assert.notNull(server, "云主机不存在");
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            taskExecutor.execute(() -> {
                cloudServerRepository.recycle(id, context.getTarget());
                // 关机
                if (!BocloudStatus.Server.STOPPED.name().equalsIgnoreCase(server.getStatus())) {
                    BocloudResult result = cloudServerService.stop(id, context);
                    if (result.isSuccess()) {
                        // 等待关机成功，否则有些云平台的会删除不了
                        try {
                            waitTask(id);
                        } catch (Exception e) {
                            logger.error("Get error message:{}", e);
                        }
                    }
                }
                // 回收站生成记录
                String spec = server.getCpu() + "核/" + server.getMemory() + "GB/" + server.getDisk() + "GB";
                Recycled recycled = new Recycled(server.getName(), server.getUuid(),
                        ResourceCategory.Computer.name() + "-" + server.getVendorType(), server.getId(),
                        server.getProjectId(), server.getCatalog().name(), spec);
                recycled.setTenantId(server.getTenantId());
                recycled.setUserId(server.getOwnerId());
                recycled.setProjectId(server.getProjectId());
                recycled.setMenderId(server.getMenderId());
                recycled.setOwnerId(server.getOwnerId());
                logger.info("ims发送 recycled 数据到cos：{}", JSONObject.toJSON(recycled));
                BocloudResult joinRecycle = cosInternalService.joinRecycle(recycled);
                logger.info("生成回收站记录结果：{}", JSONObject.toJSON(joinRecycle));
                RequestContext requestContext = new RequestContext(server.getCatalog(), server.getTenantId(),
                        server.getCreatorId(), server.getProjectId(), null);
                // 发送站内信
                NotifyMessage notifyMessage = new NotifyMessage(requestContext, "云主机放入回收站通知",
                        "云主机【" + server.getName() + "】已关机放入回收站", true, false);
                amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
                String operate = vendor.getType().toLowerCase() + ".vm";
                OperateResult message = new OperateResult(true, "云主机【" + server.getName() + "】已关机放入回收站", operate,
                        MapTools.simpleMap(Common.VENDORID, vendor.getId()), OperateCategory.ResourceEvent, context);
                resourceEventPublisher.send(message);
            });
            return new BocloudResult<>(true, "云主机【" + server.getName() + "】加入回收站任务已下发，请耐心等待结果...");
        } catch (Exception e) {
            logger.error("remove CloudServer fail:", e);
            return new BocloudResult<>(false, "云主机删除失败");
        }
    }

    /**
     * 等待关机成功
     *
     * @param serverId
     * @throws Exception
     */
    private void waitTask(Long serverId) throws Exception {
        CloudServer server = cloudServerRepository.query(serverId);
        if (null == server) {
            return;
        }
        Boolean flag = true;
        Long startTime = System.currentTimeMillis();
        while (flag) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                logger.error("Get error message:", e);
                Thread.currentThread().interrupt();
            }
            server = cloudServerRepository.query(serverId);
            if (null == server) {
                flag = false;
                break;
            }
            if (BocloudStatus.Server.STOPPED.name().equalsIgnoreCase(server.getStatus())) {
                flag = false;
                break;
            }
            Long endTime = System.currentTimeMillis();
            if (endTime - startTime > 60 * 1000 * 20) {
                flag = false;
                break;
            }
        }
    }

    @Override
    public BocloudResult restore(Long id, RequestContext context) {
        try {
            CloudServer server = cloudServerRepository.get(id);
            Assert.notNull(server, "云主机不存在");
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            cloudServerRepository.restore(id, context.getTarget());
            cloudServerService.start(id, context);
            return new BocloudResult<>(true, "云主机【" + server.getName() + "】还原成功");
        } catch (Exception e) {
            logger.error("remove CloudServer fail:", e);
            return new BocloudResult<>(false, "云主机还原失败");
        }
    }

    @Override
    public List<CloudServer> getRecycleServers(Long vendorId) {
        try {
            return cloudServerRepository.listRecycle(vendorId);
        } catch (Exception e) {
            logger.error("list recycle server fail:", e);
            return Lists.newArrayList();
        }
    }

    @Override
    public BocloudResult alteration(AlterationParam alteration) {
        CloudServer server = cloudServerRepository.getByUuid(alteration.getInstance());
        String oldStatus = "";
        try {
            Assert.notNull(server, "云主机不存在");
            oldStatus = server.getStatus();
            RequestContext context = alteration.getContext();
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            // CPU
            Integer cpu = alteration.getCpu();
            // 内存
            BigDecimal memory = alteration.getMemory();
            // 磁盘
            Integer systemDisk = alteration.getSystemDisk();

            String cloudServiceName = null;
            List<Volume> volumes = null;

            String vendorVersion = vendor.getVersion();
            CloudProvider provider = CloudProvider.valueOf(vendor.getType());
            switch (provider) {
                case OPENSTACK:
                case EASYSTACK:
                case MANAGEONE:
                case FUSIONCLOUD:
                    server.setStatus(BocloudStatus.Server.RESIZING.name());
                    cloudServerRepository.update(server);
                    //发送消息给cop
                    resourceTaskNotice.sendLogicalMessage(server, ResourceTaskNotice.Action.UPDATE);
                    volumes = volumeRepository.listByServerId(server.getId(), vendor.getId(), true);
                    // 通过卷创建的云主机修改配置时只会修改cpu和内存大小
                    if (!ListTool.isEmpty(volumes)) {
                        systemDisk = server.getDisk();
                    }
                    JSONObject object = new JSONObject();
                    object.put("cpu", cpu);
                    object.put("memory", memory);
                    object.put("disk", systemDisk);
                    Flavor flavor = serverOperationHelper.getFlavorId(vendor.getId(), provider,
                            JSONObject.parseObject(object.toJSONString(), VmGenericParam.class));
                    if (null == flavor) {
                        flavor = serverOperationHelper.createFlavor(cpu, memory, systemDisk, context, vendor);
                        Assert.notNull(flavor, "该平台没有适配的规格");
                    }
                    BocloudResult flavorResult =
                            serverDriver.resize(server.getInstanceId(), flavor.getFlavorUuid(), vendor.getUuid(), null);
                    if (flavorResult.isSuccess()) {
                        // 确认配置
                        flavorResult = serverDriver.confirmResize(server.getInstanceId(), vendor.getUuid(), null);
                        if (flavorResult.isFailed()) {
                            // 回滚
                            serverDriver.revertResize(server.getInstanceId(), vendor.getUuid(), null);
                            return flavorResult;
                        }
                    } else {
                        return flavorResult;
                    }
                    server.setCpu(cpu);
                    server.setMemory(memory);
                    server.setGmtModify(new Date());
                    // 配置升级的时候 才修改uuid为云主机对应的订单sn
                    if (alteration.getOperation().equals(AlterationParam.Operation.Upgrade)) {
                        server.setUuid(alteration.getNewInstance());
                    }
                    if (null != alteration.getUpgradeSkuId()) {
                        server.setSkuId(alteration.getUpgradeSkuId());
                    }
                    cloudServerRepository.update(server);
                    //发送消息给cop
                    resourceTaskNotice.sendLogicalMessage(server, ResourceTaskNotice.Action.UPDATE);
                    break;
                case VMWARE:
                    logger.info("自服务发起变更不触发功能，但是要能计费-VMWARE");
                    cloudServiceName = "VMware云主机";
                    Vdc vdc = vdcRepository.query(server.getVdcId());
                    Assert.notNull(vdc, "数据中心不存在");
                    Server host = serverRepository.query(server.getHostId());
                    Assert.notNull(host, "云主机所属主机不存在");
                    List<StoreHost> storeHosts = storeHostRepository.list(host.getId(), "PM");
                    Assert.notEmpty(storeHosts, "该云主机所属宿主机未绑定任何存储");
                    Map<Long, StoreHost> storageHostMap = storeHosts.stream().collect(Collectors.toMap(StoreHost::getStoreId, a -> a, (k1, k2) -> k2));
                    // 数据盘
                    List<JSONObject> addDataDisks = alteration.getAddDataDisks();
                    ServerModel model = new ServerModel(server.getName(), cpu, memory, null, server.getInstanceId());
                    model.setSystemDiskSize(systemDisk);
                    model.setVdcName(vdc.getName());
                    Long storeId = getaStoreId(server, storageHostMap);
                    DataStore datastore = dataStoreRepository.query(storeId);
                    model.setDatastore(datastore.getName());
                    // 云主机数据盘
                    if (!ListTool.isEmpty(addDataDisks)) {
                        List<Integer> disks = new ArrayList<>();
                        List<String> dataStoreNames = new ArrayList<>();
                        for (JSONObject dataDiskObj : addDataDisks) {
                            String category = dataDiskObj.getString("category");
                            Integer disk = dataDiskObj.getInteger("disk");
                            String dataDiskStore = null;
                            Long randomStoreId = getaStoreId(server, storageHostMap);
                            DataStore store = dataStoreRepository.query(randomStoreId);
                            if (null != store) {
                                dataDiskStore = store.getName();
                            }
                            if (StringUtils.isEmpty(dataDiskStore)) {
                                return new BocloudResult<>(false, "根据数据盘磁盘类型未找到合适的数据存储!");
                            }
                            disks.add(disk);
                            dataStoreNames.add(dataDiskStore);
                        }
                        model.setDisks(disks);
                        model.setDataStoreNames(dataStoreNames);
                    }
                    // 要编辑的云主机磁盘设备
                    model.setEditDiskList(alteration.getEditDataDisks());
                    BocloudResult result = serverDriver.modify(vendor.getUuid(), null, model);
                    if (result.isFailed()) {
                        return result;
                    }
                    CloudServer vm =
                            JSONObject.parseObject(JSONObject.toJSONString(result.getData()), CloudServer.class);
                    server.setCpu(vm.getCpu());
                    server.setMemory(vm.getMemory());
                    server.setDisk(vm.getDisk());
                    server.setGmtModify(new Date());
                    // 配置升级的时候 才修改uuid为云主机对应的订单sn
                    if (alteration.getOperation().equals(AlterationParam.Operation.Upgrade)) {
                        server.setUuid(alteration.getNewInstance());
                    }
                    if (null != alteration.getUpgradeSkuId()) {
                        server.setSkuId(alteration.getUpgradeSkuId());
                    }
                    cloudServerRepository.update(server);
                    //发送消息给cop
                    resourceTaskNotice.sendLogicalMessage(server, ResourceTaskNotice.Action.UPDATE);
                    volumes = volumeRepository.listByServerId(server.getId());
                    Map<String, Volume> oldMap = Maps.newHashMap();
                    for (Volume disk : volumes) {
                        oldMap.put(disk.getVolumeUuid(), disk);
                    }
                    List<Volume> newDiskDevices = vm.getDiskDevices();
                    // 新增的磁盘
                    List<Volume> addDiskDevices = new ArrayList<>();
                    // 新增磁盘设置uuid
                    if (AlterationParam.Operation.AddDisk == alteration.getOperation()) {
                        List<ElementModel> upgrade = alteration.getUpgrade();
                        for (Volume newDiskDevice : newDiskDevices) {
                            if (!oldMap.containsKey(newDiskDevice.getVolumeUuid())) {
                                addDiskDevices.add(newDiskDevice);
                            } else {
                                Volume volume = oldMap.get(newDiskDevice.getVolumeUuid());
                                if (!volume.getName().equals(newDiskDevice.getName())) {
                                    volume.setName(newDiskDevice.getName());
                                    volumeRepository.update(volume);
                                }
                            }
                        }
                        logger.info("add disk device size：{}", addDiskDevices.size());
                        logger.info("add disk element size：{}", upgrade.size());
                        if (addDiskDevices.size() == upgrade.size()) {
                            for (int i = 0; i < upgrade.size(); i++) {
                                ElementModel elementModel = upgrade.get(i);
                                String uuid = elementModel.getUuid();
                                String category = elementModel.getCategory();
                                elementModel.getSkuId();
                                addDiskDevices.get(i).setUuid(uuid);
                                addDiskDevices.get(i).setCategory(category);
                                addDiskDevices.get(i).setSkuId(elementModel.getSkuId());
                            }
                        }
                        List<Volume> newAddDisks = new ArrayList<>();
                        for (Volume disk : addDiskDevices) {
                            disk.preSave(context.getTarget(), context.getTarget(), 0L, server.getVendorId());
                            disk.setServerId(server.getId());
                            disk.setCatalog(context.getCatalog());
                            disk.setExpiredTime(server.getExpiredTime());
                            if (StringUtils.isNotBlank(disk.getDataStoreName())) {
                                DataStore dataStore = dataStoreRepository.getByName(disk.getDataStoreName(), server.getVdcId());
                                if (dataStore != null) {
                                    disk.setDataStoreId(dataStore.getId());
                                }
                            }
                            volumeRepository.save(disk);
                            sendRabbitMessage(context, disk, "云主机升级成功");
                            newAddDisks.add(disk);
                        }
                        Map<Long, Volume> usedVolumeMap = new HashMap<>();
                        if (!ListTool.isEmpty(addDataDisks)) {
                            for (JSONObject addDataDisk : addDataDisks) {
                                if (addDataDisk.containsKey("createLvm") && addDataDisk.getBoolean("createLvm")
                                        && !StringUtils.isEmpty(addDataDisk.getString("device"))) {
                                    String device = addDataDisk.getString("device");
                                    Volume existVolume = volumeRepository.getByLvmMntp(server.getId(), device);
                                    Volume findVolume = new Volume();
                                    for (Volume newAddDisk : newAddDisks) {
                                        if (addDataDisk.getInteger("disk").intValue() == newAddDisk.getSize().intValue()
                                                && !usedVolumeMap.containsKey(newAddDisk.getId())) {
                                            usedVolumeMap.put(newAddDisk.getId(), newAddDisk);
                                            findVolume = newAddDisk;
                                            break;
                                        }
                                    }
                                    BocloudResult lvmResult = null;
                                    if (null != existVolume) {
                                        findVolume.setFileSystem(existVolume.getFileSystem());
                                        lvmResult = lvmService.lvmExtend(server, vendor, addDataDisk, findVolume, context);
                                    } else {
                                        lvmResult = lvmService.lvmCreate(server, vendor, addDataDisk, findVolume, context);
                                    }
                                    //如果lvm挂载失败，调用worker删除
                                    if (lvmResult.isFailed()) {
//                                        List<String> diskUUids = new ArrayList<>();
//                                        List<String> diskNames = new ArrayList<>();
//                                        for (Volume newAddDisk : newAddDisks) {
//                                            diskUUids.add(newAddDisk.getVolumeUuid());
//                                            diskNames.add(newAddDisk.getName());
//                                        }
//                                        deleteDisk(context, server, vendor, diskUUids,diskNames);
                                        //逻辑修改，如果挂载LVM失败，磁盘不需要删除，但需要在站内信中给出明确说明
                                        sendRabbitMessage(context, findVolume, "磁盘添加成功，lvm挂载失败，原因：" + lvmResult.getMessage());
                                    }
                                }
                            }
                        }
                    } else if (AlterationParam.Operation.EditDisk == alteration.getOperation()) {
                        SyncVmwareUtils utils = new SyncVmwareUtils(cloudServerRepository, dataStoreRepository,
                                serverRepository, snapshotRepository, networkRepository, clusterRepository,
                                storeHostRepository, networkCardRepository, portGroupRepository, networkHostRepository,
                                serverConfigRepository, resourceRepository, ipRepository, imageRepository,
                                volumeRepository);
                        List<DataStore> stores = dataStoreRepository.listByVendor(vendor.getId());
                        Map<String, DataStore> storeMap = new HashMap<>();
                        stores.forEach(s -> storeMap.put(s.getStoreVal(), s));
                        utils.syncDiskDevice(storeMap, volumes, newDiskDevices, server.getVdcId(), vendor.getId(),
                                server.getId(), context.getTarget());
                        // 处理lvm
                        List<JSONObject> editDataDisks = alteration.getEditDataDisks();
                        List<ElementModel> upgrade = alteration.getUpgrade();
                        if (!ListTool.isEmpty(editDataDisks)) {
                            for (JSONObject editDataDisk : editDataDisks) {
                                Volume findVolume =
                                        volumeRepository.getDiskByName(server.getId(), editDataDisk.getString("name"));
                                Assert.notNull(findVolume, "硬盘不存在");
                                // 编辑
                                if (!ListTool.isEmpty(upgrade) && null != upgrade.get(0).getSkuId()) {
                                    findVolume.setSkuId(upgrade.get(0).getSkuId());
                                    sendRabbitMessage(context, findVolume, "云主机配置修改成功");
                                    volumeRepository.update(findVolume);
                                }
                                BocloudResult lvmResult = null;
                                if (!StringUtils.isEmpty(findVolume.getLvmMntp())) {
                                    findVolume.setFileSystem(findVolume.getFileSystem());
                                    lvmResult = lvmService.lvmResize(server, vendor, editDataDisk, findVolume, context);
                                    //如果lvm挂载失败，由于vc不提供缩盘，所以不做任何操作
                                } else {
                                    String device = editDataDisk.getString("device");
                                    if (StringUtils.isEmpty(device)) {
                                        continue;
                                    }
                                    Volume existVolume = volumeRepository.getByLvmMntp(server.getId(), device);
                                    if (null != existVolume) {
                                        findVolume.setFileSystem(existVolume.getFileSystem());
                                        lvmResult = lvmService.lvmExtend(server, vendor, editDataDisk, findVolume, context);
                                    } else {
                                        lvmResult = lvmService.lvmCreate(server, vendor, editDataDisk, findVolume, context);
                                    }
                                    List<String> diskNames = Lists.newArrayList(findVolume.getName());
                                    List<String> diskUuids = Lists.newArrayList(findVolume.getVolumeUuid());
                                    //如果lvm挂载失败，调用worker删除
                                    if (lvmResult.isFailed()) {
//                                        deleteDisk(context, server, vendor,diskUuids, diskNames);
                                        //逻辑修改，如果挂载LVM失败，磁盘不需要删除，但需要在站内信中给出明确说明
                                        sendRabbitMessage(context, findVolume, "磁盘添加成功，lvm挂载失败，原因：" + lvmResult.getMessage());
                                    }
                                }
                            }
                        }
                    } else {
                        OrderMessage message = new OrderMessage(alteration.getInstance(), Operation.Upgrade,
                                OrderItemStatus.ChangeSuccess, null, "云主机配置修改成功", server.getGmtModify(), server.getExpiredTime(), null,
                                ResourceCategory.Computer.name(), context);
                        message.setNewSn(alteration.getNewInstance());
                        amqpTemplate.convertAndSend("resource.result.queue", message);
                    }
                    break;
                case TENCENT:
                case ALIYUN:
                    cloudServiceName = "阿里云云主机";
                case HUAWEI:
                    cloudServiceName = "华为云云主机";
                case TCE:
                case AWS:
                    cloudServiceName = "AWS云主机";
                case QCLOUD:
                    logger.info("自服务发起变更不触发功能，但是要能计费-ALIYUN-HUAWEI");
                    /*
                    JSONObject pubOjbect = new JSONObject();
                    pubOjbect.put("id", server.getId());
                    pubOjbect.put(Common.VENDORID, server.getVendorId());
                    pubOjbect.put("flavorId", alteration.getFlavorId());
                    BocloudResult bocloudResult = this.resize(pubOjbect.toJSONString(), context);
                    if (bocloudResult.isFailed()) {
                        throw new RuntimeException(bocloudResult.getMessage());
                    }
                    */
                    break;
                case HCSO:
                    JSONObject huaweiObject = new JSONObject();
                    huaweiObject.put("cpu", cpu);
                    huaweiObject.put("memory", memory);
                    huaweiObject.put("zoneId", server.getZone());
                    // 获取规格类型
                    String flavorType = server.getCpuModel();
                    if (StringUtils.isEmpty(flavorType)) {
                        Flavor flavorId = flavorRepository.getByFlavorId(server.getFlavorUuid(), server.getVendorId(),
                                null);
                        if (null != flavorId) {
                            String cpuArchitecture = flavorId.getCpuArchitecture();
                            if (!StringUtils.isEmpty(cpuArchitecture) && "kunpeng".equalsIgnoreCase(cpuArchitecture)) {
                                flavorType = "arm";
                            }
                            if (!StringUtils.isEmpty(cpuArchitecture) && "x86".equalsIgnoreCase(cpuArchitecture)) {
                                flavorType = "kvm";
                            }
                        }
                    }
                    huaweiObject.put("flavorType", flavorType);
                    logger.info("flavorType : " + flavorType);
                    Flavor huaweiFlavor = serverOperationHelper.getFlavorId(vendor.getId(), provider,
                            JSONObject.parseObject(huaweiObject.toJSONString(), VmGenericParam.class));
                    if (null == huaweiFlavor) {
                        Assert.notNull(huaweiFlavor, "该平台没有适配的规格");
                    }
                    JSONObject pubCloudOjbect = new JSONObject();
                    pubCloudOjbect.put("id", server.getId());
                    pubCloudOjbect.put(Common.VENDORID, server.getVendorId());
                    pubCloudOjbect.put("flavorId", huaweiFlavor.getId());
                    pubCloudOjbect.put("skuId", alteration.getUpgradeSkuId());
                    BocloudResult hcsoBocloudResult = this.resize(pubCloudOjbect.toJSONString(), context);
                    if (hcsoBocloudResult.isFailed()) {
                        OrderMessage message = new OrderMessage(alteration.getInstance(), Operation.Upgrade,
                                OrderItemStatus.ChangeFailure, null, hcsoBocloudResult.getMessage(), server.getGmtModify(),
                                server.getExpiredTime(), null, ResourceCategory.Computer.name(), context);
                        message.setNewSn(alteration.getNewInstance());
                        message.setQuotas(alteration.getQuotas());
                        amqpTemplate.convertAndSend("resource.result.queue", message);
                        throw new RuntimeException(hcsoBocloudResult.getMessage());
                    }
                    break;
                case FUSIONSPHERE:
                    //变更cpu和men
                    if (null != cpu && null != memory) {
                        ServerModel serverModel = new ServerModel();
                        serverModel.setUri(server.getUri());
                        serverModel.setCpu(cpu);
                        //需要单独处理cpu和mem，不能直接同时修改
                        BocloudResult fcResult = serverDriver.modify(vendor.getUuid(), null, serverModel);
                        if (fcResult.isFailed()) {
                            return fcResult;
                        }
                        serverModel.setMemory(memory);
                        serverModel.setCpu(null);
                        fcResult = serverDriver.modify(vendor.getUuid(), null, serverModel);
                        if (fcResult.isFailed()) {
                            //将cpu修改为之前规格
                            serverModel.setMemory(null);
                            serverModel.setCpu(server.getCpu());
                            BocloudResult fc = serverDriver.modify(vendor.getUuid(), null, serverModel);
                            return fcResult;
                        }
                        server.setCpu(cpu);
                        server.setMemory(memory);
                        if (null != alteration.getUpgradeSkuId()) {
                            server.setSkuId(alteration.getUpgradeSkuId());
                        }
                        cloudServerRepository.update(server);
                        //发送消息给cop
                        resourceTaskNotice.sendLogicalMessage(server, ResourceTaskNotice.Action.UPDATE);
                    }
                    //磁盘变更 -- 针对一块硬盘
                    if (AlterationParam.Operation.EditDisk == alteration.getOperation() && !ListTool.isEmpty(alteration.getEditDataDisks())) {
                        List<JSONObject> editDataDisks = alteration.getEditDataDisks();
                        List<Volume> volumeList = volumeRepository.listByServerId(server.getId());
                        volumeList = volumeList.stream().filter(volume -> volume.getName().equals(editDataDisks.get(0).getString("name"))).collect(Collectors.toList());
                        Assert.notNull(volumeList, "硬盘不存在");
                        List<ElementModel> upgrade = alteration.getUpgrade();
                        Assert.notNull(volumeList, "规格信息不存在");
                        Long skuId = upgrade.get(0).getSkuId();
                        Volume volume = volumeList.get(0);
                        VolumeModel volumeModel = new VolumeModel();
                        volumeModel.setSize(editDataDisks.get(0).getInteger("disk"));
                        volumeModel.setVolumeUuid(volume.getVolumeUuid());
                        volumeModel.setInstanceId(server.getUri());
                        BocloudResult volumeResult = volumeDriver.modify(vendor.getUuid(), null, volumeModel);
                        if (volumeResult.isFailed()) {
                            return volumeResult;
                        }
                        volume.setSize(volumeModel.getSize());
                        volume.setSkuId(skuId);
                        volumeRepository.update(volume);
                    }
                    break;
                case SANGFOR:
                    logger.info("自服务发起变更不触发功能，但是要能计费-SANGFOR");
                    cloudServiceName = "深信服云主机";
                    /*
                    if (AlterationParam.Operation.Upgrade.equals(alteration.getOperation())){
                        if (null != cpu && null != memory) {
                            logger.info("开始执行数据变更");
                            ServerModel serverModel = new ServerModel();
                            serverModel.setInstanceId(server.getInstanceId());
                            serverModel.setCpu(cpu);
                            serverModel.setMemory(memory);
                            BocloudResult sangforResult = serverDriver.modify(vendor.getUuid(), null, serverModel);
                            if (sangforResult.isFailed()) {
                                ResourceEvent event = new ResourceEvent(server.getId(), "云主机配置变更", "失败",
                                        context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                                resourceEventRepository.save(event);
                                return sangforResult;
                            }
                            server.setCpu(cpu);
                            server.setMemory(memory);
                            if (alteration.getOperation().equals(AlterationParam.Operation.Upgrade)) {
                                server.setUuid(alteration.getNewInstance());
                            }
                            if (null != alteration.getUpgradeSkuId()) {
                                server.setSkuId(alteration.getUpgradeSkuId());
                            }
                            cloudServerRepository.update(server);
                            ResourceEvent event = new ResourceEvent(server.getId(), "云主机配置变更", "成功",
                                    context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                            resourceEventRepository.save(event);
                            OrderMessage message = new OrderMessage(alteration.getInstance(), Operation.Upgrade,
                                    OrderItemStatus.ChangeSuccess, null, "云主机配置修改成功", server.getGmtModify(), server.getExpiredTime(), null,
                                    ResourceCategory.Computer.name(), context);
                            message.setNewSn(alteration.getNewInstance());
                        }
                    } else if(AlterationParam.Operation.AddDisk.equals(alteration.getOperation())){
                        List<JSONObject> addDisks = alteration.getAddDataDisks();
                        if (ListTool.isEmpty(addDisks)){
                            return new BocloudResult(false, "新增磁盘不能为空");
                        }
                        JSONObject diskJo = addDisks.get(0);
                        String disk = diskJo.getString("disk");
                        Long dataStoreId = diskJo.getLong("dataStoreId");
                        String dataStoreUuid = diskJo.getString("dataStoreUuid");
                        String preallocate = diskJo.getString("preallocate");

                        Integer diskSize = Integer.valueOf(disk);
                        ServerModel serverModel = new ServerModel();
                        serverModel.setInstanceId(server.getInstanceId());
                        serverModel.setAddDiskTotal(diskSize);
                        serverModel.setCfgstorage(dataStoreUuid);
                        serverModel.setPreallocate(preallocate);
                        BocloudResult sangforResult = serverDriver.modify(vendor.getUuid(), null, serverModel);
                        if (sangforResult.isFailed()) {
                            ResourceEvent event = new ResourceEvent(server.getId(), "新增磁盘变更", "失败",
                                    context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                            resourceEventRepository.save(event);
                            return sangforResult;
                        }
                        List<Volume> oldenVolumes = volumeRepository.listByServerId(server.getId());
                        List<String> volumeNames = oldenVolumes.stream().map(Volume::getName).collect(Collectors.toList());
                        for (int i = 0; i < volumeNames.size(); i++) {
                            String s = volumeNames.get(i);
                            volumeNames.set(i, s.replace("硬盘", ""));
                        }
                        int maxIndex = Integer.parseInt(volumeNames.get(0));
                        for (String e : volumeNames) {
                            maxIndex = Math.max(Integer.parseInt(e), maxIndex);
                        }

                        String diskPolicieId, diskPolicieName;
                        if ("6.8".equals(vendorVersion)) {
                            diskPolicieId = preallocate;
                            diskPolicieName = DiskPreallocateType.valueOf(preallocate).getDesc();
                        } else {
                            diskPolicieId = oldenVolumes.get(0).getDiskPolicieUuid();
                            diskPolicieName = oldenVolumes.get(0).getDiskPolicieName();
                        }

                        Long skuId = oldenVolumes.get(0).getSkuId();
                        int disk_total = diskSize;
                        for (Volume volume : oldenVolumes) {
                            disk_total += volume.getSize();
                        }
                        server.setDisk(disk_total);
                        cloudServerRepository.update(server);
                        Volume volume = new Volume();
                        if ("6.8".equals(vendorVersion)) {
                            volume.setVolumeUuid(server.getInstanceId() + "-" + (maxIndex + 1));
                        } else {
                            volume.setVolumeUuid(server.getInstanceId() + "-ide" + (maxIndex + 1));
                        }
                        volume.setName("硬盘" + (maxIndex + 1));
                        volume.setSize(diskSize);
                        volume.setServerInstanceId(server.getInstanceId());
                        volume.setDataStoreUuid(dataStoreUuid);
                        volume.setVendorId(vendor.getId());
                        volume.setServerId(server.getId());
                        volume.setDataStoreId(dataStoreId);
                        volume.setDiskPolicieUuid(diskPolicieId);
                        volume.setDiskPolicieName(diskPolicieName);
                        volume.setGmtCreate(new Date());
                        volume.setGmtModify(new Date());
                        volume.setCreatorId(1L);
                        volume.setMenderId(1L);
                        volume.setDeleted(false);
                        volume.setBootVolume(false);
                        volume.setSkuId(skuId);
                        volume.setUuid(alteration.getNewInstance());
                        volumeRepository.save(volume);
                        ResourceEvent event = new ResourceEvent(server.getId(), "新增磁盘变更", "成功",
                                context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                        resourceEventRepository.save(event);
                    }
                    */
                    break;
                default:
                    return new BocloudResult<>(false, "暂不支持");
            }
            List<CmdbInfo> infos = Lists.newArrayList();
            infos.add(CmdbInfoConvertor.getInfo(server, "modify", null));
            cmdbMessagePublisher.send(CmdbInfoConvertor.getModel(BoCloudService.IMS, infos));

            OrderMessage message = new OrderMessage(alteration.getInstance(), Operation.Upgrade,
                    OrderItemStatus.ChangeSuccess, null, "云主机配置修改成功", server.getGmtModify(), server.getExpiredTime(), null,
                    ResourceCategory.Computer.name(), context);
            message.setNewSn(alteration.getNewInstance());
            amqpTemplate.convertAndSend("resource.result.queue", message);

            // 是否开启OA消息
            boolean oaEnable = zjkyOAService.getOaEnable();
            if (oaEnable) {
                String instanceNo = alteration.getInstanceNo();
                List<User> managerUserList = null;
                User creatorUser = null;
                // 申请人
                Long creatorId = context.getTarget();
                BocloudResult<User> userResult;
                if (creatorId != null && creatorId.longValue() > 0L) {
                    userResult = smsUserService.detail(creatorId);
                    if (userResult.isSuccess()) {
                        creatorUser = userResult.getData();
                    }
                }
                // 管理员
                Long roleId = 1L;// 角色为超级管理员
                List<Param> params = new ArrayList<>();
                params.add(new Param(MapTools.simpleMap("status", "NORMAL"), Sign.EQ));
                userResult = smsUserService.listUsers(roleId, new Pager(1, Integer.MAX_VALUE, params, null));
                if (userResult.isSuccess()) {
                    JSONObject json = JSON.parseObject(String.valueOf(userResult.getData()), JSONObject.class);
                    managerUserList = json.getJSONArray(Common.ROWS).toJavaList(User.class);
                }
                StringBuilder vmSb = new StringBuilder();
                vmSb.append(server.getName()).append('(').append(server.getManagerIp()).append(")");
                // 发给管理员
                if (managerUserList != null && !managerUserList.isEmpty() && creatorUser != null) {
                    String creatorName = creatorUser.getName();
                    String subject = creatorName + "提交的" + cloudServiceName + "【" + vmSb.toString() + "】变更申请已经办结，云主机所属的云平台名称为【"
                            + vendor.getName() + "】，流程工单的申请单号为【" + instanceNo + "】。";
                    logger.info(subject);
                    for (User managerUser : managerUserList) {
                        sendOaMessage(subject, managerUser);
                    }
                }
            }

            return new BocloudResult<>(true, "升级成功");
        } catch (Exception e) {
            logger.error("Get error message：{}", e);
            return new BocloudResult<>(false, e.getMessage());
        } finally {
        }
    }

    private void sendRabbitMessage(RequestContext context, Volume findVolume, String s2) {
        OrderMessage message = new OrderMessage(findVolume.getUuid(), Operation.Upgrade,
                OrderItemStatus.ChangeSuccess, null, s2, findVolume.getGmtModify(),
                findVolume.getExpiredTime(), null, ResourceCategory.Computer.name(), context);
        message.setNewSn(findVolume.getUuid());
        logger.info("LVM操作失败，发送rabbitmq消息：routingKey is ：resource.result.queue ，message is ：" + JSONObject.toJSONString(message));
        amqpTemplate.convertAndSend("resource.result.queue", message);
    }

    /**
     * @param storageHostMap
     * @return java.lang.Long
     * @Author: lxy
     * @Description: 取资源池非禁用状态下存储
     * @Date 2021/7/2 11:46
     * @Param server
     * @throws:
     **/
    private Long getaStoreId(CloudServer server, Map<Long, StoreHost> storageHostMap) throws Exception {
        List<PoolGroupRelation> poolGroupRelations = new ArrayList<>();
        List<Long> storeEnable = new ArrayList<>();
        //说明是自服务申请
        if (null != server.getPoolGroupId()) {
            //首选查询资源池中设置禁用的资源
            poolGroupRelations = poolGroupRelationRepository.listByGroupId(server.getPoolGroupId());
            if (!ListTool.isEmpty(poolGroupRelations)) {
                storeEnable = poolGroupRelations.stream().filter(poolGroupRelation -> storageHostMap.containsKey(poolGroupRelation.getTarget())).filter(poolGroupRelation -> !poolGroupRelation.getEnabled()).map(PoolGroupRelation::getTarget).collect(Collectors.toList());
                storeEnable.stream().forEach(
                        store -> {
                            storageHostMap.remove(store);
                        }
                );
            }
        }
        if (storageHostMap.isEmpty()) {
            throw new Exception("没有可用存储资源，请联系管理员！");
        }
        int rn = new Random().nextInt(storageHostMap.size());
        int k = 0;
        Long storeId = null;
        for (Long key : storageHostMap.keySet()) {
            if (k == rn) {
                storeId = key;
                continue;
            }
            k++;
        }
        if (storeId == null) {
            throw new Exception("没有找到可用存储资源，请联系管理员！");
        }
        return storeId;
    }

    /**
     * @param server
     * @param vendor
     * @param diskUUids
     * @param diskNames
     * @return void
     * @Author: lxy
     * @Description: 删除磁盘
     * @Date 2021/7/1 15:12
     * @Param context
     * @throws:
     **/
    private void deleteDisk(RequestContext context, CloudServer server, CloudVendor vendor, List<String> diskUUids, List<String> diskNames) {
        //卸载lvm
        BocloudResult result = deleteLvmDisk(diskUUids, server, vendor, context);
        if (result.isFailed() && !result.getMessage().contains("There was a problem while connecting")) {
            Assert.isTrue(result.isSuccess(), result.getMessage());
        }
        //删除物理盘
        result = serverDriver.deleteDisk(vendor.getUuid(), server.getInstanceId(), diskUUids);
        Assert.isTrue(result.isSuccess(), result.getMessage());
        List<Volume> volumes = volumeRepository.listByNames(server.getId(), diskNames);
        Integer disk = 0;
        for (Volume volume : volumes) {
            disk += null == volume.getSize() ? 0 : volume.getSize();
            volumeRepository.remove(volume.getId(), context.getTarget());
        }
        Integer oldDisk = null == server.getDisk() ? 0 : server.getDisk();
        server.setDisk(oldDisk - disk < 0 ? 0 : oldDisk - disk);
        server.setGmtModify(new Date());
        cloudServerRepository.update(server);
    }

    /**
     * @param server
     * @param vendor
     * @param context
     * @return com.bocloud.common.model.BocloudResult
     * @Author: lxy
     * @Description: 如果存在lvm挂载，需要先卸载
     * @Date 2021/6/25 18:26
     * @Param diskNames
     * @throws:
     **/
    private BocloudResult deleteLvmDisk(List<String> diskUUids, CloudServer server, CloudVendor vendor, RequestContext context) {
        //查询需要卸载lvm的磁盘uuid
        BocloudResult selectDiskUuid = serverDriver.selectDiskUuid(vendor.getUuid(), server.getInstanceId(), diskUUids);
        Assert.isTrue(selectDiskUuid.isSuccess(), selectDiskUuid.getMessage());
        List<String> spaceIds =
                JSONArray.parseArray(JSONObject.toJSONString(selectDiskUuid.getData()), String.class);
        //调用lvm卸载
        BocloudResult lvmDelete = lvmService.lvmDelete(server, vendor, spaceIds, context);
        if (lvmDelete.isFailed()) {
            if (lvmDelete.getMessage().contains("There was a problem while connecting")) {
                return lvmDelete;
            } else {
                Assert.isTrue(lvmDelete.isSuccess(), lvmDelete.getMessage());
            }
        }
        List<JSONObject> lvmResult = JSONArray.parseArray(JSONObject.toJSONString(lvmDelete.getData()), JSONObject.class);
        //lvm卸载失败的磁盘id
        List<String> delSpecIds = new ArrayList<>();
        if (!ListTool.isEmpty(lvmResult)) {
            for (JSONObject lvm : lvmResult) {
                String scsiId = lvm.get("scsiId").toString();
                if (spaceIds.contains(scsiId)) {
                    delSpecIds.add(scsiId);
                }
            }
        }
        if (ListTool.isEmpty(delSpecIds)) {
            return new BocloudResult<>(true, "lvm删除成功");
        } else {
            return new BocloudResult<>(false, "lvm删除失败，请重新操作，id值为：" + JSONObject.toJSON(delSpecIds));
        }
    }

    /**
     * 公有云自服务云主机变更
     *
     * @param params
     * @param context
     * @return
     */
    public BocloudResult resize(String params, RequestContext context) {
        JSONObject object = JSONTools.isJSONObj(params);
        if (null == object) {
            return new BocloudResult<>(false, "参数格式错误");
        }
        // 云主机ID
        Long id = object.getLong(Common.ID);
        // 云平台ID
        Long vendorId = object.getLong(Common.VENDORID);
        // 规格ID
        Long flavorId = object.getLong("flavorId");
        Boolean forceStop = object.getBoolean("forceStop") == null ? false : object.getBoolean("forceStop");
        String path = CloudServer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            // 云供应商
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Assert.notNull(vendor, "云平台不存在");
            // 云主机
            CloudServer server = cloudServerRepository.query(id);
            Assert.notNull(server, "云主机不存在");
            String serverStatus = server.getStatus();
            if (!forceStop) {
                if ("RUNNING".equalsIgnoreCase(server.getStatus())) {
                    return new BocloudResult<>(false, "配置调整需要在关机状态下操作!");
                }
            }
            // 规格
            Flavor finalFlavor = flavorRepository.query(flavorId);
            Assert.notNull(finalFlavor, "规格不存在");

            if (CloudProvider.HUAWEI.name().equals(vendor.getType())
                    || CloudProvider.HCSO.name().equals(vendor.getType())
                    || CloudProvider.FUSIONCLOUD.name().equals(vendor.getType())
                    || CloudProvider.MANAGEONE.name().equals(vendor.getType())
                    || CloudProvider.QCLOUD.name().equals(vendor.getType())
                    || CloudProvider.PQCLOUD.name().equals(vendor.getType())
                    || CloudProvider.TCE.name().equals(vendor.getType())
                    || CloudProvider.AZURE.name().equals(vendor.getType())
                    || CloudProvider.AWS.name().equals(vendor.getType())
                    || CloudProvider.ALIYUN.name().equals(vendor.getType())
                    || CloudProvider.TENCENT.name().equals(vendor.getType())) {
                // 支持 高配 --> 低配 所以不做判断处理
            } else {
                // 新配置的CPU，磁盘，内存不能小于原配置
                if (finalFlavor.getCpu() < server.getCpu() || finalFlavor.getDisk() < server.getDisk()
                        || (finalFlavor.getMemory().compareTo(server.getMemory()) < 0)) {
                    return new BocloudResult<>(false, "CPU、磁盘和内存大小不能小于原配置");
                }
            }
            try {
                // 修改配置
                BocloudResult result = new BocloudResult<>();
                if (CloudProvider.TENCENT.name().equals(vendor.getType())
                        || CloudProvider.TCE.name().equals(vendor.getType())) {
                    result = serverDriver.resize(server.getInstanceId(), finalFlavor.getFlavorUuid(), forceStop,
                            vendor.getUuid(), server.getRegionId());
                } else {
                    result = serverDriver.resize(server.getInstanceId(), finalFlavor.getFlavorUuid(), vendor.getUuid(),
                            server.getRegionId());
                }
                if (result.isSuccess()) {
                    // 更新配置
                    ServerModel model = serverOperationHelper.parseObject(result.getData(), ServerModel.class);
                    if (model.getStatus().equals(BocloudStatus.Server.ERROR.name())) {
                        server.setStatus(BocloudStatus.Server.EXCEPTION.name());
                    } else {
                        server.setStatus(model.getStatus());
                    }
                    server.setCpu(finalFlavor.getCpu());
                    server.setMemory(finalFlavor.getMemory());
                    server.setFlavorName(finalFlavor.getName());
                    server.setFlavorUuid(finalFlavor.getFlavorUuid());
                    cloudServerRepository.update(server);
                } else {
                    server.setStatus(serverStatus);
                    cloudServerRepository.update(server);
                }
                //发送消息给cop
                resourceTaskNotice.sendLogicalMessage(server, ResourceTaskNotice.Action.UPDATE);
                ResourceEvent event = new ResourceEvent(server.getId(), "规格变更", result.isSuccess() ? "成功" : "失败",
                        context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                resourceEventRepository.save(event);
                return new BocloudResult<>(result.isSuccess(), result.isSuccess() ? "规格变更成功" : result.getMessage());
            } catch (Exception e) {
                server.setStatus(serverStatus);
                cloudServerRepository.update(server);
                //发送消息给cop
                resourceTaskNotice.sendLogicalMessage(server, ResourceTaskNotice.Action.UPDATE);
                logger.error("cloudServer resize error:", e);
                return new BocloudResult<>(false, "规格变更失败：" + e.getMessage());
            }
        } catch (Exception e) {
            logger.error("CloudServer resize error:", e);
            return new BocloudResult<>(false, "修改配置失败 :" + e.getMessage());
        }
    }

    @Override
    public BocloudResult upgradeConfig(String params, RequestContext context) {
        logger.info("变更参数：" + params);
        JSONObject jsonObject = JSONObject.parseObject(params);
        if (null == jsonObject) {
            logger.error("Incorrect parameter format");
            return new BocloudResult<>(false, "参数格式错误");
        }
        // 云主机ID
        Long id = jsonObject.getLong("id");
        // CPU
        Integer cpu = jsonObject.getInteger("cpu");
        // 内存
        BigDecimal memory = jsonObject.getBigDecimal("memory");
        // 磁盘
        Integer systemDisk = jsonObject.getInteger("systemDisk");
        // 数据盘
        Integer dataDisk = jsonObject.getInteger("dataDisk");
        try {
            CloudServer server = cloudServerRepository.get(id);
            Assert.notNull(server, "云主机不存在");
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            ServerModel model = new ServerModel();
            model.setCpu(cpu);
            model.setMemory(memory);
            model.setInstanceId(server.getInstanceId());
            model.setName(server.getName());
            model.setSystemDiskSize(systemDisk);
            model.setDataDisk(dataDisk);
            Vdc vdc = vdcRepository.query(server.getVdcId());
            Assert.notNull(vdc, "数据中心不存在");
            model.setVdcName(vdc.getName());
            Server host = serverRepository.query(server.getHostId());
            Assert.notNull(host, "云主机所属主机不存在");
            List<StoreHost> storeHosts = storeHostRepository.list(host.getId(), "PM");
            if (ListTool.isEmpty(storeHosts)) {
                return new BocloudResult<>(false, "该云主机所属宿主机未绑定任何存储");
            }
            Long storeId = storeHosts.get(new Random().nextInt(storeHosts.size())).getStoreId();
            DataStore datastore = dataStoreRepository.query(storeId);
            model.setDatastore(datastore.getName());
            BocloudResult result = serverDriver.modify(vendor.getUuid(), null, model);
            if (result.isFailed()) {
                return result;
            }
            CloudServer vm = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), CloudServer.class);
            server.setCpu(vm.getCpu());
            server.setMemory(vm.getMemory());
            server.setDisk(vm.getDisk());
            server.setGmtModify(new Date());
            cloudServerRepository.update(server);
            SyncVmwareUtils utils = new SyncVmwareUtils(cloudServerRepository, dataStoreRepository, serverRepository,
                    snapshotRepository, networkRepository, clusterRepository, storeHostRepository, networkCardRepository,
                    portGroupRepository, networkHostRepository, serverConfigRepository, resourceRepository, ipRepository,
                    imageRepository, volumeRepository);
            List<Volume> volumes = volumeRepository.listByServerId(server.getId());
            List<DataStore> stores = dataStoreRepository.listByVendor(vendor.getId());
            Map<String, DataStore> storeMap = new HashMap<>();
            stores.forEach(s -> storeMap.put(s.getStoreVal(), s));
            utils.syncDiskDevice(storeMap, volumes, vm.getDiskDevices(), server.getVdcId(), vendor.getId(),
                    server.getId(), context.getTarget());
            List<CmdbInfo> infos = Lists.newArrayList();
            infos.add(CmdbInfoConvertor.getInfo(server, "modify", null));
            cmdbMessagePublisher.send(CmdbInfoConvertor.getModel(BoCloudService.IMS, infos));
            if (null != dataDisk && 0L != dataDisk) {
                JSONObject object = new JSONObject();
                object.put("pasd", server.receivePswd());
                if ("LINUX".equalsIgnoreCase(server.getOsCategory())) {
                    object.put("host", server.getManagerIp());
                    object.put("category", "Linux");
                    object.put("device", "/dev/sdb");
                } else {
                    String managerIp = null;
                    String privateIps = server.getPrivateIps();
                    if (!StringUtils.isEmpty(privateIps)) {
                        List<JSONObject> objects = JSONArray.parseArray(privateIps, JSONObject.class);
                        for (JSONObject privateIp : objects) {
                            String networkName = privateIp.getString("networkName");
                            if (!StringUtils.isEmpty(networkName) && networkName.contains("mngt-paas")) {
                                managerIp = privateIp.getString("address");
                                break;
                            }
                        }
                    }
                    if (StringUtils.isEmpty(managerIp)) {
                        managerIp = server.getManagerIp();
                    }
                    object.put("host", managerIp);
                    object.put("category", "Windows");
                }
                this.formatDisk(server.getId(), object, context);
            }
            return new BocloudResult<>(true, "升级配置成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "升级配置失败");
        }
    }

    @Override
    public BocloudResult extension(ExtensionParam param) {
        try {
            CloudServer server = cloudServerRepository.getByUuid(param.getInstance());
            Assert.notNull(server, "云主机不存在");
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(server.getExpiredTime());
            calendar.add(Calendar.MONTH, param.getExtension());
            server.setExpiredTime(calendar.getTime());
            cloudServerRepository.update(server);

            OrderMessage message = new OrderMessage(param.getInstance(), Operation.Extension,
                    OrderItemStatus.ExtensionSuccess, param.getExtension(), "云主机延期成功", null, calendar.getTime(), null,
                    ResourceCategory.Computer.name(), param.getContext());
            amqpTemplate.convertAndSend("resource.result.queue", message);
            return new BocloudResult<>(true, "云主机延期成功");
        } catch (Exception e) {
            logger.error("postpone cms fail:", e);
            return new BocloudResult<>(false, "云主机延期失败：" + e.getMessage());
        }
    }

    @Override
    public BocloudResult cancelation(CancelationParam param) {
        CloudServer server = null;
        try {
            server = cloudServerRepository.getByUuid(param.getInstance());
            Assert.notNull(server, "云主机不存在");
        } catch (Exception e) {
            logger.error("Get error message：{}", e.getMessage());
            return new BocloudResult<>(false, e.getMessage());
        }
        RequestContext context = param.getContext();
        String path = CloudServer.class.getSimpleName() + "_" + server.getId();
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            CloudProvider provider = CloudProvider.valueOf(vendor.getType());
            List<Volume> dataVolumes = null;
            switch (provider) {
                case VMWARE:
                case FUSIONSPHERE:
                case SANGFOR:
                    dataVolumes = volumeRepository.listByServerId(server.getId(), server.getVendorId(), false);
                    break;
                case SMARTX:
                    dataVolumes = volumeRepository.listVolumeByServerIdAndMultiattach(server.getId(), false);
                    break;
                default:
                    dataVolumes = volumeRepository.listByServerId(server.getId(), server.getVendorId(), true);
                    break;
            }

            BocloudResult result = null;
            if (CloudProvider.FUSIONSPHERE.name().equals(vendor.getType())) {
                result = serverDriver.remove(server.getUri(), server.getName(), vendor.getUuid(), server.getRegionId());
            } else if (CloudProvider.SANGFOR.name().equals(vendor.getType())) {
                result = serverDriver.remove(server.getInstanceId(), server.getName(), vendor.getUuid(), null);
                //result = new BocloudResult(true, "删除成功");
            } else {
                result = serverDriver.remove(server.getInstanceId(), server.getName(), vendor.getUuid(), server.getRegionId());
            }
            if (result.isFailed()) {
                return result;
            }
            result = serverOperationHelper.remove(server.getId(), null, vendor, server, null, context,
                    param.getIsDeletePublicIp());
            if (result.isFailed()) {
                return result;
            }
            OrderMessage message =
                    new OrderMessage(param.getInstance(), Operation.Cancelation, OrderItemStatus.UnsubscribeSuccess, null,
                            result.getMessage(), null, null, null, ResourceCategory.Computer.name(), context);
            List<QuotaBean> quotas = new ArrayList<>();
            quotas.add(new QuotaBean("compute." + vendor.getType().toLowerCase() + ".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);
            if (!ListTool.isEmpty(dataVolumes)) {
                OrderMessage volumeOrderMessage =
                        new OrderMessage(null, Operation.Cancelation, OrderItemStatus.UnsubscribeSuccess, null, "云硬盘退订成功",
                                null, null, new ArrayList<>(), ResourceCategory.Storage.name(), context);
                volumeOrderMessage.setCategory(ResourceCategory.Storage.name());
                for (Volume volume : dataVolumes) {
                    volumeOrderMessage.setSn(volume.getUuid());
                    List<QuotaBean> volumeQuotas = new ArrayList<>();
                    volumeQuotas.add(new QuotaBean(vendor.getType().toLowerCase() + ".standard.volume", 1));
                    volumeQuotas.add(new QuotaBean("meta.disk", volume.getSize()));
                    volumeOrderMessage.setQuotas(volumeQuotas);
                    amqpTemplate.convertAndSend("resource.result.queue", volumeOrderMessage);
                }
            }
            // 清空回收站
            cosInternalService.recycle(server.getUuid());
            return new BocloudResult<>(true, "云主机退订成功");
        } catch (Exception e) {
            logger.error("Get error message：{}", e.getMessage());
            return new BocloudResult<>(false, "云主机退订失败：" + e.getMessage());
        }
    }

    @Override
    public BocloudResult formatDisk(Long id, JSONObject object, RequestContext context) {
        try {
            CloudServer server = null;
            if (null == id) {
                server = cloudServerRepository.getByInstanceId(object.getString("instanceId"));
            } else {
                server = cloudServerRepository.query(id);
            }
            Assert.notNull(server, "云主机不存在");
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            String host = object.getString("host");
            String category = object.getString("category");
            String pasd = object.getString("pasd");
            Map<String, Object> params = new HashMap<>();
            List<Map<String, Object>> targets = new ArrayList<>();
            Map<String, Object> target = new HashMap<>();
            target.put("host", host);
            Encryptor encryptor = new AESEncrptor();
            target.put("pasd", encryptor.encrypt(pasd, null));
            Map<String, Object> module = new HashMap<>();
            if ("Linux".equalsIgnoreCase(category)) {
                target.put("user", "root");
                target.put("category", "Linux");
                target.put("port", 22);
                Map<String, Object> args = new HashMap<>();
                args.put("device", object.getString("device"));
                module.put("args", args);
                module.put("name", "resizefs");
                Map<String, Object> options = new HashMap<>();
                options.put("become", true);
                module.put("options", options);
                params.put("timeout", 1800);
            } else if ("Windows".equalsIgnoreCase(category)) {
                target.put("category", "Windows");
                target.put("user", "administrator");
                target.put("port", 5986);
                target.put("rawName", host);
                Map<String, Object> winDisk = new HashMap<>();
                winDisk.put("driver", "E");
                winDisk.put("disk_number", 1);
                Map<String, Object> args = new HashMap<>();
                args.put("win_disk", winDisk);
                module.put("args", args);
                module.put("name", "resizefs_windows");
                params.put("timeout", 1800);
            }
            targets.add(target);
            params.put("targets", targets);
            params.put("module", module);
            params.put("response", "async");
            BocloudResult result = diskFormatService.format(vendor, server, params, context);
            if (result.isFailed()) {
                return result;
            }
            return new BocloudResult<>(true, "格式化磁盘任务已下发，请耐心等待执行结果...");
        } catch (Exception e) {
            logger.info("Get error message：{}", e.getMessage());
            return new BocloudResult<>(false, "格式化磁盘任务下发失败");
        }
    }

    @Override
    public BocloudResult createServer(JSONObject param, RequestContext context, String queue) {
        try {
            // 位置
            JSONObject location = param.getJSONObject("location");
            // 配置信息
            JSONObject configs = param.getJSONObject("configs");
            // 资源归属信息
            configs.put("poolGroupId", location.getLong("poolGroupId"));
            configs.put("businessId", location.getLong("businessId"));
            configs.put("projectId", location.getLong("projectId"));
            configs.put("creatorId", location.getLong("creatorId"));
            configs.put("ownerId", location.getLong("ownerId"));
            configs.put("menderId", location.getLong("menderId"));
            String password = configs.getString("password");
            if (!StringUtils.isEmpty(password)) {
                Encryptor encryptor = new AESEncrptor();
                try {
                    password = encryptor.decrypt(password.trim(), null);
                    configs.put("password", password);
                } catch (Exception e) {
                    logger.error("Get error message:{}", e);
                    return new BocloudResult<>(false, e.getMessage());
                }
            }
            configs.put("networks", param.get("networks"));
            configs.put("groups", param.get("groups"));
            CloudVendor vendor = cloudVendorRepository.query(location.getLong("vendorId"));
            Assert.notNull(vendor, "当前可用域未绑定云平台");
            CloudProvider provider = CloudProvider.valueOf(vendor.getType());
            Map<Long, List<Ip>> networkConfigs = new HashMap<>();
            // 网卡端口组关联集合
            Map<Long, Long> portGroupConfigs = new HashMap<>();
            // 通过调度策略分配的宿主机和存储
            String nsxNetworkName = null;
            List<JSONObject> targetObjs = new ArrayList<>();
            if (CloudProvider.VMWARE == provider) {
                Long imageId = configs.getLong("imageId");
                if (null != imageId) {
                    Image targetImage = imageRepository.query(imageId);
                    Assert.notNull(targetImage, "未找到合适的镜像");
                    CloudServer template = cloudServerRepository.query(targetImage.getTemplateId());
                    Assert.notNull(template, "未找到合适的云主机模板");
                    configs.put("templateId", targetImage.getTemplateId());
                }
                Map<String, Object> assignMap = Maps.newHashMap();
                assignMap.put("Cpu", configs.getLong("cpu"));
                assignMap.put("Memory", configs.getBigDecimal("memory"));
                assignMap.put("Disk", configs.getLong("disk"));
                assignMap.put("Instance", 1);
                // 根据计算资源池获取可分配宿主机，存储
                BocloudResult<List<JSONObject>> BocloudResult = resSchedulerEngine
                        .selectHost(location.getLong("poolGroupId"), "Cpu", assignMap, configs.getString("diskCategory"));
                Assert.isTrue(BocloudResult.isSuccess(), BocloudResult.getMessage());
                targetObjs = BocloudResult.getData();
                // 判断vcenter是否使用nsx网络
                Long vpcId = configs.getLong("vpcId");
                if (null != vpcId) {

                } else {
                    JSONArray ipConfigs = configs.getJSONArray("networkCardConfigs");
                    IpPool ipPool = new IpPool();
                    for (int j = 0; j < ipConfigs.size(); j++) {
                        JSONObject config = ipConfigs.getJSONObject(j);
                        Long poolId = config.getLong("ipPoolId");
                        Long networkCardId = config.getLong("networkCardId");
                        Long portGroupId = config.getLong("portGroupId");
                        portGroupConfigs.put(networkCardId, portGroupId);
                        if (null != poolId && 0L != poolId) {
                            ipPool = ipPoolRepository.query(poolId);
                            Assert.notNull(ipPool, "IP池不存在");
                        }
                        String ipPolicy = config.getString("ipPolicy");
                        if (StringUtils.isEmpty(ipPolicy)) {
                            ipPolicy = "Auto";
                        }
                        switch (config.getString("ipPolicy")) {
                            case "Dhcp":
                                BocloudResult<List<Ip>> dhcpIpResult =
                                        ipService.achieveDhcpIps(poolId, 1L, ipPool.getVersion());
                                Assert.isTrue(dhcpIpResult.isSuccess(), dhcpIpResult.getMessage());
                                List<Ip> dhcpIps = dhcpIpResult.getData();
                                networkConfigs.put(networkCardId, dhcpIps);
                                break;
                            case "Auto":
                                BocloudResult<List<Ip>> autoIpData =
                                        ipService.achievePoolIps(poolId, 1L, ipPool.getVersion());
                                Assert.isTrue(autoIpData.isSuccess(), autoIpData.getMessage());
                                List<Ip> autoIps = autoIpData.getData();
                                networkConfigs.put(networkCardId, autoIps);
                                break;
                            case "Manual":
                                List<String> addresses = JSONArray
                                        .parseArray(JSONObject.toJSONString(config.getJSONArray("address")), String.class);
                                List<Ip> manualIps = ipRepository.listIpsByPool(poolId, addresses);
                                Assert.notEmpty(manualIps, "未设置正确的IP地址");
                                networkConfigs.put(networkCardId, manualIps);
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
            // 数据预处理
            JSONObject newObj = configs;
            newObj.put("name", configs.getString("name") + "_" + IDFactory.instance().mac());
            if (!ListTool.isEmpty(targetObjs)) {
                JSONObject targetObj = targetObjs.get(0);
                newObj.put("storeId", targetObj.getLong("storeId"));
                newObj.put("hostId", targetObj.getLong("hostId"));
                // 数据盘分配存储
                if (newObj.containsKey("addDiskList")) {
                    List<JSONObject> addDiskList =
                            JSONArray.parseArray(newObj.getString("addDiskList"), JSONObject.class);
                    if (!ListTool.isEmpty(addDiskList)) {
                        List<String> dataStoreNames =
                                resSchedulerEngine.assignStore(targetObj.getLong("hostId"), addDiskList);
                        if (ListTool.isEmpty(dataStoreNames)) {
                            return new BocloudResult<>(false, "为云主机分配数据盘存储发生错误");
                        }
                        newObj.put("dataStoreNames", dataStoreNames);
                        List<Integer> disks = new ArrayList<>();
                        for (JSONObject dataDisk : addDiskList) {
                            Integer disk = dataDisk.getInteger("disk");
                            disks.add(disk);
                        }
                        newObj.put("disks", disks);
                    }
                    newObj.put("dataDiskList", newObj.getString("addDiskList"));
                    newObj.remove("addDiskList");
                }
            }
            BocloudResult<ServerBuilder> builderResult = serverOperationHelper.getProcess(provider, vendor, context);
            Assert.isTrue(builderResult.isSuccess(), builderResult.getMessage());
            ServerBuilder process = builderResult.getData();
            BocloudResult<ProcessResult> result = null;
            if (CloudProvider.VMWARE == provider) {
                Map<Long, Ip> ipMap = new HashMap<>();
                for (Map.Entry<Long, List<Ip>> entry : networkConfigs.entrySet()) {
                    Long networkCardId = entry.getKey();
                    List<Ip> ips = entry.getValue();
                    Ip ip = ips.get(0);
                    ipMap.put(networkCardId, ip);
                }
                result = serverOperationHelper.prepareVcenter(newObj, context, vendor, process, new ArrayList<>(),
                        nsxNetworkName);
            } else {
                result = serverOperationHelper.prepare(
                        JSONObject.parseObject(newObj.toJSONString(), VmGenericParam.class), context, vendor, process);
            }
            Assert.isTrue(result.isSuccess(), result.getMessage());
            result.getData().setServerBuilder(process);
            ProcessResult processResult = result.getData();
            // 启动一个线程从MQ上获取数据
            new Thread(() -> serverOperationHelper.builder(vendor.getType(), vendor.getId(),
                    processResult.getCloudServer(), context, process, queue)).start();
            return new BocloudResult<>(true, "申请任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("Apply virtual machine error", e);
            return new BocloudResult<>(false, "申请云主机失败：" + e.getMessage());
        }
    }

    @Override
    public BocloudResult recycle(String uuid, RequestContext context) {
        String path = CloudServer.class.getSimpleName() + "_" + uuid;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudServer server = cloudServerRepository.getByUuid(uuid);
            Assert.notNull(server, "云主机不存在");
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(server, "云平台不存在");
            Long id = server.getId();
            cloudServerRepository.recycle(id, context.getTarget());
            taskExecutor.execute(() -> {
                // 关机
                if (!BocloudStatus.Server.STOPPED.name().equalsIgnoreCase(server.getStatus())) {
                    BocloudResult result = cloudServerService.stop(id, context);
                    if (result.isSuccess()) {
                        // 等待关机成功，否则有些云平台的会删除不了
                        try {
                            waitTask(id);
                        } catch (Exception e) {
                            logger.error("Get error message:{}", e);
                        }
                    } else {
                        server.setRecycle(false);
                        cloudServerRepository.update(server);
                    }
                }
                // 回收站生成记录
                String spec = server.getCpu() + "核/" + server.getMemory() + "GB/" + server.getDisk() + "GB";
                Recycled recycled = new Recycled(server.getName(), server.getUuid(),
                        ResourceCategory.Computer.name() + "-" + server.getVendorType(), server.getId(),
                        server.getProjectId(), server.getCatalog().name(), spec);
                recycled.setTenantId(server.getTenantId());
                recycled.setUserId(server.getOwnerId());
                recycled.setProjectId(server.getProjectId());
                recycled.setMenderId(server.getMenderId());
                recycled.setOwnerId(server.getOwnerId());
                logger.info("ims发送 recycled 数据到cos：{}", JSONObject.toJSON(recycled));
                BocloudResult joinRecycle = cosInternalService.joinRecycle(recycled);
                logger.info("生成回收站记录结果：{}", JSONObject.toJSON(joinRecycle));
                RequestContext requestContext = new RequestContext(server.getCatalog(), server.getTenantId(),
                        server.getCreatorId(), server.getProjectId(), null);
                // 发送站内信
                NotifyMessage notifyMessage = new NotifyMessage(requestContext, "云主机放入回收站通知",
                        "云主机【" + server.getName() + "】已关机放入回收站", true, false);
                amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
                String operate = vendor.getType().toLowerCase() + ".vm";
                OperateResult message = new OperateResult(true, "云主机【" + server.getName() + "】已放入回收站", operate,
                        MapTools.simpleMap(Common.VENDORID, vendor.getId()), OperateCategory.ResourceEvent, context);
                resourceEventPublisher.send(message);
            });
            return new BocloudResult<>(true, "云主机【" + server.getName() + "】加入回收站任务已下发，请耐心等待结果...");
        } catch (Exception e) {
            logger.error("云主机加入回收站失败:", e);
            return new BocloudResult<>(false, "云主机加入回收站失败：" + e.getMessage());
        }

    }

    @Override
    public BocloudResult batchRecycle(String param, RequestContext context) {
        try {
            JSONObject batchParams = JSON.parseObject(param, JSONObject.class);
            List<String> resourceUuidArray = JSON.parseArray(batchParams.getString("resourceUuids"), String.class);
            if (ListTool.isEmpty(resourceUuidArray)) {
                return new BocloudResult<>(false, "参数格式错误！");
            }
            for (String uuid : resourceUuidArray) {
                this.recycle(uuid, context);
            }
            return new BocloudResult<>(true, "批量移入回收站任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("批量加入回收站异常：" + e.getMessage());
            return new BocloudResult<>(false, "批量加入回收站异常：" + e.getMessage());
        }
    }

}