package com.bocloud.ims.service.builder;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.compute.ServerDriver;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.model.ServerModel;
import com.bocloud.cmp.model.sangfor.*;
import com.bocloud.cmp.provider.v68.utils.SangForServerHelper;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.RequestContext;
import com.bocloud.ims.entity.common.ServiceCategory;
import com.bocloud.ims.entity.common.ServiceSku;
import com.bocloud.ims.entity.params.SkuParams;
import com.bocloud.ims.entity.resource.CloudServer;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.DataStore;
import com.bocloud.ims.entity.resource.Network;
import com.bocloud.ims.entity.resource.Server;
import com.bocloud.ims.entity.resource.Volume;
import com.bocloud.ims.repository.resource.CloudServerRepository;
import com.bocloud.ims.repository.resource.DataStoreRepository;
import com.bocloud.ims.repository.resource.NetworkRepository;
import com.bocloud.ims.repository.resource.ServerRepository;
import com.bocloud.ims.repository.resource.VolumeRepository;
import com.bocloud.ims.service.common.ShtermService;
import com.bocloud.ims.service.internal.CosInternalService;
import com.bocloud.ims.service.transporter.vendor.SangforV68Transporter;
import com.bocloud.ims.service.utils.BeanUtils;
import com.bocloud.ims.service.utils.SangforConvertUtils;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

public class SangforBuilder implements ServerBuilder {
    private static Logger logger = LoggerFactory.getLogger(SangforBuilder.class);

    private RequestContext context;
    private CloudVendor vendor;
    private ServerDriver serverDriver;
    private ServerModel model;
    private CloudServerRepository cloudServerRepository;
    private VolumeRepository volumeRepository;
    private DataStoreRepository dataStoreRepository;
    private NetworkRepository networkRepository;
    private CosInternalService cosInternalService;
    private ServerRepository serverRepository;
    private ShtermService shtermService;

    public SangforBuilder(RequestContext context, CloudVendor vendor, ServerDriver serverDriver, CloudServerRepository cloudServerRepository,
                          VolumeRepository volumeRepository, DataStoreRepository dataStoreRepository, NetworkRepository networkRepository,
                          CosInternalService cosInternalService, ServerRepository serverRepository,
                          ShtermService shtermService) {
        this.context = context;
        this.vendor = vendor;
        this.serverDriver = serverDriver;
        this.cloudServerRepository = cloudServerRepository;
        this.volumeRepository = volumeRepository;
        this.dataStoreRepository = dataStoreRepository;
        this.networkRepository = networkRepository;
        this.cosInternalService = cosInternalService;
        this.serverRepository = serverRepository;
        this.shtermService = shtermService;
    }

    @Override
    public BocloudResult<ServerModel> prepare(JSONObject object) throws Exception {
        try {
            String disksText = object.getString("disks");
            object.remove("disks");// 需要去掉，不然下面object转ServerModel会报错

            model = new ServerModel();
            model = JSONObject.parseObject(object.toJSONString(), ServerModel.class);
            boolean isNewlyCreated = Optional.ofNullable(model.getIsNewlyCreated()).orElse(false);
            model.setIsNewlyCreated(isNewlyCreated);

            String version = object.getString("version");
            model.setVendorVersion(version);

            // 新克隆虚拟机的名称
            String name = object.getString("name");
            // 宿主机的uuid。
            String hostUuid = object.getString("hostUuid");
            if (!StringUtils.hasLength(hostUuid)) {
                hostUuid = object.getString("alwaysTryHost");
            }

            List<SangforNetWorkConfig> newWorkConfigs1 = JSON.parseArray(object.getString("newWorkConfigs"), SangforNetWorkConfig.class);
            // 克隆方式
            String cloneType = object.getString("cloneType");
            // 自动启动
            Boolean start = object.getBoolean("start");
            // HA虚拟机
            Boolean haEnable = object.getBoolean("ha");
            // 虚拟机所在分组id
            String groupUuid = object.getString("groupUuid");
            //虚拟机创建完成后是否需要开机
            Boolean powerOn = object.getBoolean("powerOn");
            //虚拟机所属资源池Id;
            String resourceId = object.getString("resourceId");
            //虚拟机镜像Id;
            String imageUuid = object.getString("imageUuid");
            // 存储策略
            String storagePolicy = object.getString("storagePolicy");
            // 主机名
            String hostname = object.getString("hostname");
            // 描述信息
            String remark = object.getString("remark");
            // 网络连接
            // 网络（网卡）
            String interfaceType = object.getString("interfaceType");
            String interfaceId = object.getString("interfaceId");
            String mac = object.getString("mac");
            String ip = object.getString("ip");
            if ("6.8".equals(version) && ip != null) {
                ip = ip.replaceAll("\n", ",");
            }

            String mask = object.getString("mask");
            String gateway = object.getString("gateway");
            String primaryDns = object.getString("primaryDns");
            String secondaryDns = object.getString("secondaryDns");
            Boolean disableNet = object.getBoolean("disableNet");
            String alwaysTryHost = object.getString("alwaysTryHost");
            String storage = object.getString("storage");
            //深信服6.8系统盘大小
            Integer disk = object.getInteger("disk");
            Integer diskStorage = object.getInteger("diskStorage");
            String sourceVmId = object.getString("sourceVmId");
            String vmUuid = object.getString("vmUuid");
            String password = object.getString("password");

            if ("6.8".equals(version)) {
                Integer cpu = object.getInteger("cpu");
                String memory = object.getString("memory");
                String portUuid = object.getString("portUuid");
                model.setCpu(cpu);
                model.setMemory(new BigDecimal(memory));
                model.setPortUuid(portUuid);

                List<SangforDiskModel> disks = JSON.parseArray(disksText, SangforDiskModel.class);
                if (disks != null && !disks.isEmpty()) {
                    model.setSangforDisks(disks);
                }

                String bridgename = object.getString("bridgename");
                if (StringUtils.hasLength(bridgename)) {
                    model.setBridgename(bridgename);
                }
                String dns1 = object.getString("dns1");
                if (StringUtils.hasLength(dns1)) {
                    model.setPrimaryDns(dns1);
                }
                String dns2 = object.getString("dns2");
                if (StringUtils.hasLength(dns2)) {
                    model.setSecondaryDns(dns2);
                }

                String osName = model.getOsName();
                if (StringUtils.hasLength(osName)) {
                    osName = SangForServerHelper.getDetailOsName(osName);
                    model.setOsName(osName);
                }
                if (disk !=null){
                    model.setSystemDiskSize(disk);
                }
                if (diskStorage !=null){
                    model.setDiskStorage(diskStorage);
                }
//                if (newWorkConfigs !=null){
//                    model.setSangforNetWorkConfigs();
//                }
            }

            if (isNewlyCreated) {
                String bridge = object.getString("bridge");// 网络的ID

                Integer sockets = model.getSockets();
                Integer cores = model.getCores();
                if (sockets != null && cores != null) {
                    model.setCpu(sockets * cores);
                }
                model.setDisk(object.getInteger("disk_total"));
                model.setPowerOn(powerOn);
                model.setImageUuid(imageUuid);
                model.setResourceId(resourceId);
                model.setGateway(gateway);
                model.setInterfaceId(bridge);
            } else {
                model.setSangforNetWorkConfigs(newWorkConfigs1);
                model.setName(name);
                model.setTargetNode(hostUuid);
                model.setStorage(storage);
                model.setCloneType(cloneType);
                model.setStart(start);
                model.setStoragePolicy(storagePolicy);
                model.setHa(haEnable);
                model.setGroup(groupUuid);
                model.setHostName(hostname);
                model.setRemark(remark);

                model.setInterfaceId(interfaceId);
                model.setInterfaceType(interfaceType);
                model.setMac(mac);
                model.setIp(ip);
                model.setMask(mask);
                model.setGateway(gateway);
                model.setPrimaryDns(primaryDns);
                model.setSecondaryDns(secondaryDns);
                model.setDisableNet(disableNet);
                model.setAlwaysTryHost(alwaysTryHost);
                model.setDisk(disk);
                model.setPassword(password);
                if (sourceVmId != null){
                    model.setSourceVmId(sourceVmId);
                    model.setInstanceId(sourceVmId);
                }else {
                    model.setSourceVmId(vmUuid);
                    model.setInstanceId(vmUuid);
                }
            }
            return new BocloudResult<>(true, model, "success");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return new BocloudResult<>(false, "失败");
        }
    }

    @Override
    public BocloudResult<CloudServer> builder(CloudServer cloudServer) throws Exception {
        Boolean isAddShterm;
        try {
            String vendorVersion = model.getVendorVersion();
            if (!StringUtils.hasLength(vendorVersion)) {
                throw new IllegalArgumentException("云平台版本不能为空");
            }
            SangforServerModel sangforServerModel = new SangforServerModel();
            if (vendorVersion.equals("6.8") && model.getIsNewlyCreated()) {
                if (StringUtils.hasLength(model.getHostName())) {
                    //ISO方式新增虚拟机，自定义设置主机名称，结果创建失败，提示系统繁忙 sxp:2023.7.10
                    model.setHostName(null);
                }

                BeanUtils.copyPropertiesIgnoreNull(model, sangforServerModel);
                List<SangforDiskModel> disks = new ArrayList<>();
                SangforDiskModel diskModel = new SangforDiskModel();
                diskModel.setId("ide0");
                diskModel.setPreallocate(model.getPreallocate());
                diskModel.setSize_mb(model.getDisk()*1024);
                disks.add(diskModel);

                String bridgeName = model.getBridgename();
                String portUuid = model.getPortUuid();
                String primaryDns = model.getPrimaryDns();
                String secondaryDns = model.getSecondaryDns();

                List<String> dnsList = new ArrayList<>(2);
                if (StringUtils.hasLength(primaryDns)) {
                    dnsList.add(primaryDns);
                }
                if (StringUtils.hasLength(secondaryDns)) {
                    dnsList.add(secondaryDns);
                }

                Long networkId = Long.valueOf(model.getInterfaceId());
                Network networkOfDb = networkRepository.get(Network.class, networkId);
                Assert.notNull(networkOfDb, "不存在id为" + networkId + "的网络信息");
                String networkDeviceId = networkOfDb.getGuid();

                List<SangforNetwork> networks = new ArrayList<>();
                SangforNetwork network = new SangforNetwork();
                network.setConnect(1);
                network.setVif_id("net0");
                network.setDevice_id(networkDeviceId);
                //network.setModel(model.getNetworkcardType());
                network.setModel("virtio");
                if (StringUtils.hasLength(bridgeName)) {
                    network.setName(bridgeName);
                }
                if (StringUtils.hasLength(portUuid)) {
                    network.setPort_id(portUuid);
                }
                SangforNetworkIpInfo info = new SangforNetworkIpInfo();
                info.setIp_address(model.getIp());
                info.setNetmask(model.getMask());
                info.setGateway(model.getGateway());
                if (!dnsList.isEmpty()) {
                    info.setDns(dnsList);
                }
                network.setIp_info(info);
                networks.add(network);

                sangforServerModel.setDisks(disks);
                sangforServerModel.setNetworks(networks);
                sangforServerModel.setImage_id(model.getIso());
                sangforServerModel.setAz_id(model.getResourceId());
                sangforServerModel.setGroup_id(model.getDir());
                sangforServerModel.setStorage_id(model.getCfgstorage());
                sangforServerModel.setMemory(model.getMemory().intValue());
                Integer powerOn = 0;
                if (model.getPowerOn() != null && model.getPowerOn().booleanValue()) {
                    powerOn = 1;
                }
                if ("-1".equals(model.getLifespan())) {
                    sangforServerModel.setLifespan("");
                }
                sangforServerModel.setPower_on(powerOn);
                JSONObject object = new JSONObject();
                object.put("id", model.getAlways_try_host());
                sangforServerModel.setLocation(object);
                sangforServerModel.setHostname(model.getHostName());
                sangforServerModel.setCpu(model.getCpuType());
            } else {
                BeanUtils.copyPropertiesIgnoreNull(model, sangforServerModel);
                sangforServerModel.setHostname(model.getHostName());
                sangforServerModel.setCpu(model.getCpuType());
            }

            BocloudResult result;
            long timeout = 5L * 60 * 1000;   // 虚拟机创建、克隆（快速克隆、连接克隆）超时时间设为5分钟
            long sleepTime = 5L * 1000;      // 虚拟机创建、克隆（快速克隆、连接克隆）睡眠时间设为5秒钟

            //全新虚拟创建逻辑
            if (model.getIsNewlyCreated()) {
                sangforServerModel.setOsname(model.getOsName());
                sangforServerModel.setMemory(model.getMemory().intValue());
                sangforServerModel.setAlwaysTryHost(model.getAlways_try_host());
                // 创建全新虚拟机
                long begin = System.currentTimeMillis();

                logger.info("全新虚拟机创建model参数:{}", JSONObject.toJSONString(sangforServerModel));
                result = serverDriver.createSangfor(vendor.getUuid(), null, sangforServerModel);
                logger.info("创建全新虚拟机result:{}", JSON.toJSONString(result));
                if (result.isFailed()) {
                    cloudServerRepository.remove(cloudServer.getId(), context.getTarget());
                    logger.error("创建全新虚拟机失败：{}", result.getMessage());
                    return result;
                }

                if (vendor.getVersion().equals("6.8") && CloudProvider.SANGFOR.name().equalsIgnoreCase(vendor.getType())) {
                    Object data = result.getData();
                    if (data == null) {
                        return new BocloudResult<>(false, "创建完深信服V6.8全新虚拟后result.getData信息为空");
                    }
                    long start = System.currentTimeMillis();
                    String message;
                    String serverListStr = JSON.toJSONString(data);
                    List<SangforServerModel> serverModelList = JSON.parseArray(serverListStr, SangforServerModel.class);
                    if (serverModelList != null && !serverModelList.isEmpty()) {
                        SangforServerModel serverModel = serverModelList.get(0);
                        String newVmInstanceId = serverModel.getInstanceId();

                        boolean waitIp = false;
                        List<SangforNetwork> networks = serverModel.getNetworks();
                        if (networks == null || networks.isEmpty()) {
                            waitIp = true;
                            message = "虚拟机创建成功，正在等待网络信息的生成...";
                        } else {
                            message = "虚拟机创建成功";
                        }
                        logger.info(message);

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

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

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

                        if (waitIp) {
                            message = "虚拟机创建成功,等待网络信息的生成超时，等待同步信息后获得完整的虚拟机信息";
                        } else {
                            message = "虚拟机创建成功,已经获取到网络信息";
                        }
                        logger.info(message);
                    } else {
                        cloudServer.setStatus("STOPPED");
                        cloudServerRepository.update(cloudServer);
                        message = "虚拟机创建成功,但是未获取到虚拟机的信息，等待同步信息后获得完整的虚拟机信息";
                        logger.warn(message);
                    }

                    long cost = System.currentTimeMillis() - begin;
                    logger.info("全新虚拟机创建耗时{}ms", cost);
                } else {
                    Boolean flag = false;
                    int i = 1;
                    long l = System.currentTimeMillis();
                    while (System.currentTimeMillis() - l < timeout) {
                        Thread.sleep(5 * 1000);
                        BocloudResult bocloudResult = serverDriver.list(vendor.getUuid(), null, cloudServer.getName());
                        if (bocloudResult.isFailed() || bocloudResult.getData() == null) {
                            break;
                        }
                        List<SangforServerModel> serverModelList = JSON.parseArray(JSON.toJSON(bocloudResult.getData()).toString(), SangforServerModel.class);
                        List<CloudServer> servers = SangforConvertUtils.serverConver(serverModelList);
                        List<Volume> volumes = SangforConvertUtils.volumeConver(serverModelList);
                        logger.info("第{}次查询创建结果：\nserver:{}\nvolume:{}\n", i++, JSONObject.toJSONString(servers), JSONObject.toJSONString(volumes));
                        for (CloudServer svr : servers) {
                            String name = svr.getName();
                            String status = svr.getStatus();
                            if (!name.equals(cloudServer.getName())) {
                                continue;
                            }
                            if (!"RUNNING".equals(status) && !"STOPPED".equals(status)) {
                                break;
                            }
                            // 同步虚拟机信息
                            BeanUtils.copyPropertiesIgnoreNull(svr, cloudServer);
                            // ip地址预配置
                            if (StringUtils.isEmpty(cloudServer.getPrivateIps()) && !StringUtils.isEmpty(model.getIp())) {
                                JSONObject privateIps = new JSONObject();
                                JSONObject net0 = new JSONObject();
                                privateIps.put("net0", net0);
                                net0.put(model.getIp(), 1);
                                cloudServer.setPrivateIps(privateIps.toString());
                                cloudServer.setManagerIp(model.getIp());
                            }
                            // 克隆时给虚拟机绑定服务类型和规格
                            createServiceSku(cloudServer, volumes, vendor);
                            // 添加虚拟机卷
                            Map<String, Long> dataStoreIdMap = dataStoreRepository.listByVendor(vendor.getId()).stream()
                                    .filter(e -> "VS".equals(e.getType()) || "OTHER".equals(e.getType())).collect(Collectors.toMap(DataStore::getGuid, DataStore::getId));
                            volumes.forEach(e -> {
                                e.setVendorId(vendor.getId());
                                e.setServerId(cloudServer.getId());
                                e.setDataStoreId(dataStoreIdMap.get(e.getDataStoreUuid()));
                                e.setGmtCreate(new Date());
                                e.setGmtModify(new Date());
                                e.setCreatorId(1L);
                                e.setMenderId(1L);
                                e.setDeleted(false);
                                e.setBootVolume(true);
                            });
                            cloudServerRepository.update(cloudServer);
                            volumeRepository.batchSave(volumes, volumes.size());
                            flag = true;
                            break;
                        }
                        if (flag) {
                            logger.info("信息同步完成...");
                            break;
                        }
                    }
                    boolean isTimeout = System.currentTimeMillis() - l > timeout;
                    if (isTimeout) {
                        return new BocloudResult<>(false, "创建虚拟机超时失败，请检查深信服HCI是否创建成功");
                    }
                }
            } else {
                // 克隆虚拟机
//                Long networkId = Long.valueOf(model.getInterfaceId());

                Long dataStoreId = Long.valueOf(model.getStorage());
                DataStore dataStore = dataStoreRepository.get(DataStore.class, dataStoreId);
                Assert.notNull(dataStore, "不存在对应物理存储");
                sangforServerModel.setStorage(dataStore.getGuid());//克隆虚拟机的参数

                if (model.getDiskStorage() !=null) {
                    Long diskStorageId = Long.valueOf(model.getDiskStorage());
                    DataStore diskDataStore = dataStoreRepository.get(DataStore.class, diskStorageId);
                    Assert.notNull(diskDataStore, "磁盘所选物理存储不存在");
                    sangforServerModel.setDiskStorageUuid(diskDataStore.getGuid());
                }

//                Network network = networkRepository.get(Network.class, networkId);
//                Assert.notNull(network, "不存在对应网络");
//                sangforServerModel.setBvsId(network.getGuid());//修改虚拟机的参数
//                sangforServerModel.setBridgename(network.getName());//修改虚拟机的参数

                if (model.getSourceVmId() !=null && model.getSourceVmId().length()<5){
                    CloudServer sourceVm = cloudServerRepository.query(Long.valueOf(model.getSourceVmId()));
                    Assert.notNull(sourceVm, "源虚拟机不存在");
                    sangforServerModel.setVmid(sourceVm.getInstanceId());//克隆虚拟机的参数
                    sangforServerModel.setInstanceId(sourceVm.getInstanceId());//修改虚拟机的参数
                }else {
                    sangforServerModel.setVmid(model.getSourceVmId());//克隆虚拟机的参数
                    sangforServerModel.setInstanceId(model.getSourceVmId());//修改虚拟机的参数
                }

                sangforServerModel.setNetWorkConfigs(model.getSangforNetWorkConfigs());

                if ("6.8".equals(vendorVersion)) {
                    Integer systemDiskSize = model.getSystemDiskSize();

                    sangforServerModel.setCores(model.getCpu());//cpu
                    sangforServerModel.setMemory(model.getMemory().intValue());//memory
                    sangforServerModel.setBootdisk(new BigDecimal(model.getSystemDiskSize()).multiply(new BigDecimal(1024)).toString());//系统盘大小
                    sangforServerModel.setDisks(model.getSangforDisks());
                    sangforServerModel.setCloneType("fast");
                    sangforServerModel.setDescription(model.getRemark());
                    sangforServerModel.setPassword(model.getPassword());
                }

                logger.info("虚拟机克隆model参数:{}", JSON.toJSONString(sangforServerModel));
                long begin = System.currentTimeMillis();

                result = serverDriver.cloneSangfor(vendor.getUuid(), null, sangforServerModel);
                if (result.isFailed()) {
                    if (result.getData() == null) {
                        result.setData(cloudServer);
                    }
                    cloudServerRepository.remove(cloudServer.getId(), context.getTarget());
                    logger.error("虚拟机克隆失败：{}", result.getMessage());
                    return result;
                }

                long start = System.currentTimeMillis();

                if ("6.8".equals(vendorVersion)) {
                    String message;
                    String serverListStr = JSON.toJSONString(result.getData());
                    List<SangforServerModel> serverModelList = JSON.parseArray(serverListStr, SangforServerModel.class);
                    if (serverModelList != null && !serverModelList.isEmpty()) {
                        SangforServerModel serverModel = serverModelList.get(0);
                        String newVmInstanceId = serverModel.getInstanceId();

                        boolean waitIp = false;
                        List<SangforNetwork> networks = serverModel.getNetworks();
                        if (networks == null || networks.isEmpty()) {
                            waitIp = true;
                            message = "虚拟机创建成功，正在等待网络信息的生成...";
                        } else {
                            message = "虚拟机创建成功";
                        }
                        logger.info(message);

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

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

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

                        if (waitIp) {
                            message = "虚拟机创建成功,等待网络信息的生成超时，等待同步信息后获得完整的虚拟机信息";
                        } else {
                            message = "虚拟机创建成功,已经获取到网络信息";
                        }
                        logger.info(message);
                    } else {
                        cloudServer.setStatus("STOPPED");
                        cloudServerRepository.update(cloudServer);
                        message = "虚拟机创建成功,但是未获取到虚拟机的信息，等待同步信息后获得完整的虚拟机信息";
                        logger.warn(message);
                    }

                    isAddShterm = cloudServer.getIsAddShterm();
                    if (isAddShterm == null) {
                        isAddShterm = Boolean.TRUE;
                    }
                    // 向堡垒机发送新增云主机的消息
                    if (isAddShterm) {
                        shtermService.addShterm(cloudServer);
                    }

                    long cost = System.currentTimeMillis() - begin;
                    logger.info("克隆虚拟机耗时{}ms", cost);
                } else {
                    if ("full".equals(sangforServerModel.getCloneType())) {
                        timeout = 20L * 60 * 1000;   //全量虚拟机克隆耗时较长
                        sleepTime = 30L * 1000;
                    }
                    Boolean flag = false;
                    int i = 1;

                    while (System.currentTimeMillis() - start < timeout) {
                        try {
                            Thread.sleep(sleepTime);
                        } catch (InterruptedException e) {
                            logger.error("虚拟机克隆失败", e);
                        }
                        BocloudResult bocloudResult = serverDriver.list(vendor.getUuid(), null, model.getName());
                        if (bocloudResult.isFailed() || bocloudResult.getData() == null) {
                            break;
                        }
                        List<SangforServerModel> serverModelList = JSON.parseArray(JSON.toJSON(bocloudResult.getData()).toString(), SangforServerModel.class);
                        List<CloudServer> servers = SangforConvertUtils.serverConver(serverModelList);
                        List<Volume> volumes = SangforConvertUtils.volumeConver(serverModelList);
                        logger.info("第{}次查询创建结果：\nserver:{}\nvolume:{}\n", i++, JSONObject.toJSONString(servers), JSONObject.toJSONString(volumes));
                        for (CloudServer svr : servers) {
                            String name = svr.getName();
                            String status = svr.getStatus();
                            if (!name.equals(model.getName())) {
                                continue;
                            }
                            if (!"RUNNING".equals(status) && !"STOPPED".equals(status)) {
                                break;
                            }
                            // 同步虚拟机信息
                            BeanUtils.copyPropertiesIgnoreNull(svr, cloudServer);
                            // ip地址预配置
                            if (StringUtils.isEmpty(cloudServer.getPrivateIps()) && !StringUtils.isEmpty(model.getIp())) {
                                JSONObject privateIps = new JSONObject();
                                JSONObject net0 = new JSONObject();
                                privateIps.put("net0", net0);
                                net0.put(model.getIp(), 1);
                                cloudServer.setPrivateIps(privateIps.toString());
                                cloudServer.setManagerIp(model.getIp());
                            }
                            // 克隆时给虚拟机绑定服务类型和规格
                            createServiceSku(cloudServer, volumes, vendor);
                            // 添加虚拟机卷
                            Map<String, Long> dataStoreIdMap = dataStoreRepository.listByVendor(vendor.getId()).stream()
                                    .filter(e -> "VS".equals(e.getType()) || "OTHER".equals(e.getType())).collect(Collectors.toMap(DataStore::getGuid, DataStore::getId));
                            volumes.forEach(e -> {
                                e.setVendorId(vendor.getId());
                                e.setServerId(cloudServer.getId());
                                e.setDataStoreId(dataStoreIdMap.get(e.getDataStoreUuid()));
                                e.setGmtCreate(new Date());
                                e.setGmtModify(new Date());
                                e.setCreatorId(1L);
                                e.setMenderId(1L);
                                e.setDeleted(false);
                                e.setBootVolume(true);
                            });
                            cloudServerRepository.update(cloudServer);
                            volumeRepository.batchSave(volumes, volumes.size());
                            flag = true;
                            break;
                        }
                        if (flag) {
                            logger.info("信息同步完成...");
                            break;
                        }
                    }
                    boolean isTimeout = System.currentTimeMillis() - start > timeout;
                    if (isTimeout) {
                        return new BocloudResult<>(false, "克隆虚拟机超时失败，请检查深信服HCI是否克隆成功");
                    }
                    if (flag) {
                        isAddShterm = cloudServer.getIsAddShterm();
                        if (isAddShterm == null) {
                            isAddShterm = Boolean.TRUE;
                        }
                        // 向堡垒机发送新增云主机的消息
                        if (isAddShterm) {
                            shtermService.addShterm(cloudServer);
                        }
                    }
                }
                if (result.isFailed()) {
                    return new BocloudResult<>(false, cloudServer, result.getMessage());
                }
                cloudServerRepository.update(cloudServer);
            }
            return new BocloudResult<>(true, cloudServer, "云主机创建成功");
        } catch (Exception e) {
            logger.error("云主机创建失败", e);
            return new BocloudResult<>(false, cloudServer, "云主机创建失败，" + e.getMessage());
        }
    }

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

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

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

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

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

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

}
