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.driver.network.NetworkInterfaceDriver;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.entity.enums.InstanceType;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.entity.enums.VolumeCategory;
import com.bocloud.cmp.model.ElasticIpGenericParam;
import com.bocloud.cmp.model.NetworkInterfaceModel;
import com.bocloud.cmp.model.ServerModel;
import com.bocloud.common.enums.ResourceCatalog;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.OperateResult;
import com.bocloud.common.model.OperateResult.OperateCategory;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.ListTool;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.interfaces.resource.ElasticIpService;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.service.utils.IpRangeUtil;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.util.*;

public class AliServerBuilder implements ServerBuilder {

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

    private static OperateCategory operateCategory = OperateResult.OperateCategory.ResourceEvent;

    private CloudServerRepository cloudServerRepository;
    private ResourceRepository resourceRepository;
    private ResourceEventRepository resourceEventRepository;
    private ImageRepository imageRepository;
    private VolumeRepository volumeRepository;
    private ServerDriver serverDriver;
    private RequestContext context;
    private CloudVendor vendor;
    private ServerModel model;
    private KeypairRepository keypairRepository;
    private SecurityGroupRepository securityGroupRepository;
    private ServerSgroupRepository serverSgroupRepository;
    private ServerKeypairRepository serverKeypairRepository;
    private FlavorRepository flavorRepository;
    private SubnetRepository subnetRepository;
    private TagRepository tagRepository;
    private NetworkInterfaceRepository networkInterfaceRepository;
    private NetworkInterfaceDriver networkInterfaceDriver;
    private ResourceEventPublisher resourceEventPublisher;
    private ElasticIpService elasticIpService;
    private ElasticIpRepository elasticIpRepository;

    public AliServerBuilder(CloudServerRepository cloudServerRepository, ResourceRepository resourceRepository,
                            ResourceEventRepository resourceEventRepository, ImageRepository imageRepository,
                            VolumeRepository volumeRepository, ServerDriver serverDriver, RequestContext context, CloudVendor vendor,
                            KeypairRepository keypairRepository, SecurityGroupRepository securityGroupRepository,
                            ServerSgroupRepository serverSgroupRepository, ServerKeypairRepository serverKeypairRepository,
                            FlavorRepository flavorRepository, SubnetRepository subnetRepository, TagRepository tagRepository,
                            NetworkInterfaceRepository networkInterfaceRepository, NetworkInterfaceDriver networkInterfaceDriver,
                            ResourceEventPublisher resourceEventPublisher, ElasticIpService elasticIpService,
                            ElasticIpRepository elasticIpRepository) {
        super();
        this.keypairRepository = keypairRepository;
        this.securityGroupRepository = securityGroupRepository;
        this.serverSgroupRepository = serverSgroupRepository;
        this.serverKeypairRepository = serverKeypairRepository;
        this.cloudServerRepository = cloudServerRepository;
        this.resourceRepository = resourceRepository;
        this.resourceEventRepository = resourceEventRepository;
        this.imageRepository = imageRepository;
        this.volumeRepository = volumeRepository;
        this.serverDriver = serverDriver;
        this.context = context;
        this.vendor = vendor;
        this.flavorRepository = flavorRepository;
        this.subnetRepository = subnetRepository;
        this.tagRepository = tagRepository;
        this.networkInterfaceRepository = networkInterfaceRepository;
        this.networkInterfaceDriver = networkInterfaceDriver;
        this.resourceEventPublisher = resourceEventPublisher;
        this.elasticIpService = elasticIpService;
        this.elasticIpRepository = elasticIpRepository;
    }

    @Override
    public BocloudResult<ServerModel> prepare(JSONObject object) throws Exception {

        String name = object.getString(Common.NAME);// 云主机名
        String remark = object.getString("remark");// 描述
        model = new ServerModel(name, remark);
        Integer internetMaxBandwidthIn = object.getInteger("internetMaxBandwidthIn");
        Integer internetMaxBandwidthOut = object.getInteger("internetMaxBandwidthOut");
        if (null == internetMaxBandwidthIn || 0 == internetMaxBandwidthIn) {
            internetMaxBandwidthIn = 10;
        }
        if (null == internetMaxBandwidthOut || 0 == internetMaxBandwidthOut) {
            internetMaxBandwidthOut = 10;
        }
        Image image = imageRepository.query(object.getLong("imageId"));
        if (null == image) {
            return new BocloudResult<>(false, "镜像不存在");
        }
        int imageMinDisk = image.getMinDisk().intValue();

        Integer systemDiskSize = object.getInteger("systemDiskSize");
        if (null == systemDiskSize) {
            systemDiskSize = object.getInteger("rootSize");
        }
        if (null == systemDiskSize || systemDiskSize < imageMinDisk) {
            return new BocloudResult<>(false, "系统盘大小不允许小于镜像盘允许的最小值");
        }
        model.setDisk(systemDiskSize);

        String systemDiskCategory = object.getString("systemDiskCategory");
        if (VolumeCategory.CLOUD.name().equals(systemDiskCategory)) {
            systemDiskCategory = "cloud";
        } else if (VolumeCategory.EFFICIENCY.name().equals(systemDiskCategory)) {
            systemDiskCategory = "cloud_efficiency";
        } else if (VolumeCategory.SSD.name().equals(systemDiskCategory)) {
            systemDiskCategory = "cloud_ssd";
        } else if (VolumeCategory.ESSD.name().equals(systemDiskCategory)) {
            systemDiskCategory = "cloud_essd";
        }

        String dataDisk = object.getString("dataDisk");
        if (!StringUtils.isEmpty(dataDisk)) {
            JSONArray jsonArray = new JSONArray();
            List<Object> list = JSONArray.parseArray(dataDisk);
            for (Object obj : list) {
                JSONObject jsonObject = JSONObject.parseObject(obj.toString());
                String dataDiskCategory = jsonObject.getString("dataDiskCategory");
                if (dataDiskCategory.equals(VolumeCategory.CLOUD.name())) {
                    jsonObject.put("dataDiskCategory", "cloud");
                } else if (dataDiskCategory.equals(VolumeCategory.EFFICIENCY.name())) {
                    jsonObject.put("dataDiskCategory", "cloud_efficiency");
                } else if (dataDiskCategory.equals(VolumeCategory.SSD.name())) {
                    jsonObject.put("dataDiskCategory", "cloud_ssd");
                } else if (dataDiskCategory.equals(VolumeCategory.ESSD.name())) {
                    jsonObject.put("dataDiskCategory", "cloud_essd");
                } else {
                    jsonObject.put("dataDiskCategory", "cloud");
                }
                jsonArray.add(jsonObject);
            }
            dataDisk = jsonArray.toJSONString();
        }
        String instanceType = object.getString("instanceType");
        if (StringUtils.isEmpty(instanceType)) {
            Flavor flavor = flavorRepository.query(object.getLong("flavorId"));
            if (null == flavor) {
                return new BocloudResult<>(false, "无效的规格参数！");
            }
            instanceType = flavor.getFlavorUuid();
        }
        String instanceChargeType = object.getString("instanceChargeType");
        if (null == instanceChargeType || "".equals(instanceChargeType)) {
            instanceChargeType = "PostPaid";
        }
        model.setInstanceChargeType(instanceChargeType);
        if ("PrePaid".equalsIgnoreCase(instanceChargeType)) {
            model.setAutoRenew(object.getBooleanValue("autoRenew"));
            model.setAutoRenewPeriod(
                    null == object.getInteger("autoRenewPeriod") ? 1 : object.getInteger("autoRenewPeriod"));
            model.setPeriod(null == object.getInteger("period") ? 1 : object.getInteger("period"));
            model.setPeriodUnit(
                    StringUtils.isEmpty(object.getString("periodUnit")) ? "Month" : object.getString("periodUnit"));
        }

        String subnetUuid = object.getString("subnetUuid");
        if (StringUtils.isEmpty(subnetUuid)) {
            Subnet subnet = subnetRepository.query(object.getLong("subnetId"));
            if (null == subnet) {
                return new BocloudResult<>(false, "无效的子网参数！");
            }
            String managerIp = object.getString("managerIp");
            if (!StringUtils.isEmpty(managerIp)) {
                if (!IpRangeUtil.checkIpInRange(object.getString("managerIp"), subnet.getCidr())) {
                    return new BocloudResult(false,
                            "IP(" + object.getString("managerIp") + ")不在子网CIDR(" + subnet.getCidr() + ")范围内");
                }
            }
            subnetUuid = subnet.getSubnetUuid();
        }
        model.setSubnetUuid(subnetUuid);
        model.setKeypairName(object.getString("keypairName"));
        if (!StringUtils.isEmpty(object.getString("managerIp"))) {
            model.setManagerIp(object.getString("managerIp"));
        }
        model.setSecurityGroups(
                JSONObject.parseArray(JSON.toJSONString(object.getJSONArray("securityGroups")), String.class));
        model.setTerminationProtected(object.getBooleanValue("terminationProtected"));

        model.setHasIpv6(object.getBooleanValue("hasIpv6"));
        model.setHasEip(object.getBooleanValue("hasEip"));
        model.setEipId(object.getLong("eipId"));

        model.prepareData("root", object.getString("password"), object.getString(Common.REGIONID),
                object.getString("zone"), image.getImageUuid(), instanceType, object.getString("groups"),
                object.getString("internetChargeType"), internetMaxBandwidthIn, internetMaxBandwidthOut, systemDiskSize,
                systemDiskCategory, dataDisk);
        return new BocloudResult<ServerModel>(true, model, "success");
    }

    /**
     *
     */
    @Override
    public BocloudResult<CloudServer> builder(CloudServer cloudServer) throws Exception {
        // 创建云主机
        BocloudResult result = serverDriver.create(vendor.getUuid(), model.getRegionId(), model);
        // 操作记录
        Long userId = context.getTarget();
        String handler = "云主机创建";
        ResourceEvent event = null;
        if (result.isSuccess()) {
            event = new ResourceEvent(cloudServer.getId(), handler, "成功", userId, new Date(), "VM", vendor.getId(),
                    context.getCatalog());
            String content = JSONObject.toJSONString(result.getData());
            CloudServer server = JSONObject.parseObject(content, CloudServer.class);
            cloudServer.setInstanceId(server.getInstanceId());
            cloudServer.setUuid(server.getUuid());
            cloudServer.setDisk(model.getDisk());
            cloudServer.setMemory(server.getMemory());
            cloudServer.setCpu(server.getCpu());
            cloudServer.setGmtVmCreate(server.getGmtVmCreate());
            cloudServer.setManagerIp(server.getManagerIp());
            cloudServer.setPrivateIps(server.getPrivateIps());
            cloudServer.setManagerIp(server.getPrivateIps());
            cloudServer.setPublicIps(server.getPublicIps());
            cloudServer.setDisk(server.getDisk());
            cloudServer.setFlavorUuid(server.getFlavorUuid());
            cloudServer.setOsName(server.getOsName());
            cloudServer.setRegionId(server.getRegionId());
            cloudServer.setNetworkUuid(server.getVpcUuid());
            cloudServer.setSubnetUuid(server.getVSwitchId());
            cloudServer.setZone(server.getZone());
            cloudServer.setPswd(model.getPassword());
            String imageUuid = server.getImageUuid();
            cloudServer.setImageUuid(imageUuid);
            if (null != imageUuid && !"".equals(imageUuid)) {
                Image image = imageRepository.getByImageUuid(imageUuid);
                cloudServer.setOsCategory(image.getOsCategory());
                cloudServer.setOsVersion(image.getOsVersion());
            }
            String state = server.getStatus();
            if ("Running".equalsIgnoreCase(state)) {
                cloudServer.setStatus(BocloudStatus.Server.RUNNING.name());
            } else if ("Stopped".equalsIgnoreCase(state)) {
                cloudServer.setStatus(BocloudStatus.Server.STOPPED.name());
            }
            cloudServer.setRecycle(false);
            cloudServer.setTerminationProtected(server.getTerminationProtected());
            cloudServer.setResourceGroupUuid(server.getResourceGroupUuid());
            cloudServer.setVpcUuid(server.getVpcUuid());
            // 保存标签信息
            JSONArray labelContent = model.getLabelContent();
            if (!ListTool.isEmpty(labelContent)) {
                cloudServer.setResourceLabel(JSONObject.toJSONString(labelContent));
            }
            cloudServerRepository.update(cloudServer);

            List<Volume> volumeModels = server.getDiskDevices();
            if (!ListTool.isEmpty(volumeModels)) {
                for (Volume volume : volumeModels) {
                    volume.setCreatorId(cloudServer.getCreatorId());
                    volume.setGmtCreate(new Date());
                    volume.setVendorId(vendor.getId());
                    volume.setVendorType(vendor.getType());
                    volume.setProjectId(cloudServer.getProjectId());
                    volume.setTenantId(cloudServer.getTenantId());
                    if ("system".equals(volume.getType())) {
                        volume.setBootVolume(true);
                    } else {
                        volume.setBootVolume(false);
                    }
                    volume.setServerId(cloudServer.getId());
                    volume.setRegionId(server.getRegionId());
                    volume.setCategory(convertDiskCategory(volume.getCategory()));
                    volumeRepository.save(volume);
//                    // 保存标签
//                    List<TagModel> volumeTagModels = server.getTagModels();
//                    if (!ListTool.isEmpty(volumeTagModels)) {
//                        for (TagModel tagModel : volumeTagModels) {
//                            Tag tag = new Tag(tagModel.getKey(), tagModel.getValue(), volume.getVolumeUuid());
//                            tag.setResourceType(TagType.disk.name());
//                            tag.setVendorId(vendor.getId());
//                            tag.setRegionId(server.getRegionId());
//                            tagRepository.save(tag);
//                        }
//                    }
                }
            }

            List<NetworkInterfaceModel> nics = server.getNetworkInterfaces();
            for (NetworkInterfaceModel interfaceModel : nics) {
                NetworkInterface networkInterface = networkInterfaceRepository
                        .query(interfaceModel.getNetworkInterfaceUuid(), vendor.getId());
                BocloudResult nicsResult = networkInterfaceDriver.detail(vendor.getUuid(), server.getRegionId(),
                        interfaceModel.getNetworkInterfaceUuid());
                if (null == networkInterface) {
                    networkInterface = new NetworkInterface();
                    if (nicsResult.isSuccess()) {
                        NetworkInterfaceModel networkInterfaceModel = JSONObject.parseObject(
                                JSONObject.toJSONString(nicsResult.getData()), NetworkInterfaceModel.class);
                        BeanUtils.copyProperties(networkInterfaceModel, networkInterface);
                        Subnet subnet = subnetRepository.query(networkInterfaceModel.getSubnetUuid(), vendor.getId());
                        networkInterface.setSubnetId(
                                Optional.ofNullable(subnet).map(subnetKey -> subnetKey.getId()).orElse(null));
                        networkInterface.setVpcId(
                                Optional.ofNullable(subnet).map(subnetKey -> subnetKey.getNetworkId()).orElse(null));
                        networkInterface.setSubnetName(
                                Optional.ofNullable(subnet).map(subnetKey -> subnetKey.getName()).orElse(null));
                        networkInterface.setServerId(cloudServer.getId());
                        networkInterface.setCreatorId(userId);
                        networkInterface.setVendorId(vendor.getId());
                        networkInterface.setRegionId(cloudServer.getRegionId());
                        networkInterface.setZone(cloudServer.getZone());
                        networkInterface.setSgroupUuid(Optional.ofNullable(networkInterfaceModel.getSecurityGroups())
                                .map(securityGroups -> JSON.toJSONString(securityGroups)).orElse(null));
                        networkInterface.setMacAddress(interfaceModel.getMacAddress());
                        networkInterfaceRepository.save(networkInterface);
                    }
                } else {
                    if (nicsResult.isSuccess()) {
                        NetworkInterfaceModel networkInterfaceModel = JSONObject.parseObject(
                                JSONObject.toJSONString(nicsResult.getData()), NetworkInterfaceModel.class);
                        BeanUtils.copyProperties(networkInterfaceModel, networkInterface);
                        Subnet subnet = subnetRepository.query(networkInterfaceModel.getSubnetUuid(), vendor.getId());
                        networkInterface.setSubnetId(
                                Optional.ofNullable(subnet).map(subnetKey -> subnetKey.getId()).orElse(null));
                        networkInterface.setVpcId(
                                Optional.ofNullable(subnet).map(subnetKey -> subnetKey.getNetworkId()).orElse(null));
                        networkInterface.setSubnetName(
                                Optional.ofNullable(subnet).map(subnetKey -> subnetKey.getName()).orElse(null));
                        networkInterface.setServerId(cloudServer.getId());
                        networkInterface.setCreatorId(userId);
                        networkInterface.setVendorId(vendor.getId());
                        networkInterface.setRegionId(cloudServer.getRegionId());
                        networkInterface.setZone(cloudServer.getZone());
                        networkInterface.setSgroupUuid(Optional.ofNullable(networkInterfaceModel.getSecurityGroups())
                                .map(securityGroups -> JSON.toJSONString(securityGroups)).orElse(null));
                        networkInterface.setMacAddress(interfaceModel.getMacAddress());
                        networkInterfaceRepository.update(networkInterface);
                    }
                }
            }

            List<Volume> listByServerId = volumeRepository.listByServerId(cloudServer.getId());
            cloudServer.setDiskDevices(listByServerId);

            List<String> securityGroups = server.getSecurityGroups() == null ? new ArrayList<String>()
                    : server.getSecurityGroups();
            for (String securityGroup : securityGroups) {
                SecurityGroup group = securityGroupRepository.getByGroupId(securityGroup);
                ServerSgroup serverSgroup = new ServerSgroup(cloudServer.getId(), group.getId());
                serverSgroupRepository.save(serverSgroup);
            }
            // 保存 秘钥
            if (!StringUtils.isEmpty(model.getKeypairName())) {
                updateServerKeyPair(cloudServer, vendor.getId(), model.getKeypairName());
            }
            // 保存资源
            saveResources(cloudServer, userId);
            // 创建后逻辑处理
            afterCreateProcess(cloudServer);
        } else {
            event = new ResourceEvent(cloudServer.getId(), handler, "失败", userId, new Date(), "VM", vendor.getId(),
                    context.getCatalog());
            cloudServerRepository.remove(cloudServer.getId(), context.getTarget());
        }
        resourceEventRepository.save(event);
        return result.isSuccess() ? new BocloudResult<>(true, cloudServer, "success")
                : new BocloudResult<>(false, cloudServer, result.getMessage());
    }

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

    public void afterCreateProcess(CloudServer cloudServer) {
        // 阿里云，设置IPV6及EIP、安全组
        ServerModel processModel = model;
        if (processModel.getSecurityGroups().size() > 1) {
            logger.info("阿里云云主机" + cloudServer.getInstanceId() + "修改，安全组：" + processModel.getSecurityGroups());
            ServerModel model = new ServerModel();
            model.setInstanceId(cloudServer.getInstanceId());
            model.setSecurityGroups(processModel.getSecurityGroups());
            BocloudResult modifyResult = serverDriver.modify(vendor.getUuid(), cloudServer.getRegionId(), model);
            if (modifyResult.isFailed()) {
                logger.error("安全组修改失败 ", modifyResult.getMessage());
                resourceEventPublisher.send(
                        new OperateResult(modifyResult.isSuccess(), "安全组修改失败", vendor.getType().toLowerCase() + ".vm",
                                MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
            }
        }
        try {
            if (model.getHasIpv6()) {
                JSONArray privateIps = JSONArray.parseArray(cloudServer.getPrivateIps());
                Subnet subnet = subnetRepository.query(model.getSubnetUuid(), vendor.getId());
                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("\\.", ":");
                    List<String> ipV6AddressList = Lists.newArrayList();
                    ipV6AddressList.add(ipV6Address);
                    BocloudResult assignIpv6Result = new BocloudResult(false, "Ipv6分配失败");
                    int num = 0;
                    while (num < 60) {
                        Thread.sleep(5000);
                        assignIpv6Result = networkInterfaceDriver.assignIpv6Addresses(vendor.getUuid(),
                                interfaces.get(0).getRegionId(), interfaces.get(0).getNetworkInterfaceUuid(),
                                ipV6AddressList, 1);
                        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);
                    }
                }
            }
        } 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 (model.getHasEip()) {
                Long eipId = model.getEipId();
                ElasticIp elasticIp = null;
                if (eipId == null) {
                    ElasticIp elasticIpInfo = new ElasticIp();
                    elasticIpInfo.setName("EIP_" + UUID.randomUUID());
                    elasticIpInfo.setVendorId(vendor.getId());
                    elasticIpInfo.setBandwidth("1");
                    elasticIpInfo.setRegionId(model.getRegionId());
                    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.setInstanceType(InstanceType.EcsInstance.name());
                    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));
        }
    }

    public void saveResources(CloudServer cloudServer, Long userId) {
        // 保存资源T
        List<String> ips = Lists.newArrayList();
        if (!StringUtils.isEmpty(cloudServer.getPrivateIps())) {
            List<String> objects = JSONObject.parseArray(cloudServer.getPrivateIps(), String.class);
            for (String ip : objects) {
                ips.add(ip);
            }
        }
        Resource resource = resourceRepository.query(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
                cloudServer.getId());
        if (null == resource) {
            resource = new Resource(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
                    cloudServer.getId(), JSONObject.toJSONString(ips), cloudServer.getOsCategory(), vendor.getId());
            resource.preSave(cloudServer.getName(), cloudServer.getStatus(), userId, null, context.getProject());
            resource.setInventory(JSONObject.toJSONString(cloudServer));
            resourceRepository.save(resource);
        } else {
            resource.setInventory(JSONObject.toJSONString(cloudServer));
            resource.setStatus(cloudServer.getStatus());
            resource.setMenderId(userId);
            resource.setCreatorId(userId);
            resource.setGmtModify(new Date());
            resource.setGmtCreate(new Date());
            resource.setPrivateIps(JSONObject.toJSONString(ips));
            resourceRepository.update(resource);
        }
    }

    private void updateServerKeyPair(CloudServer server, Long vendorId, String keyPairName) throws Exception {
        String keypairName = server.getKeypairName();
        if (null != keypairName && !"".equals(keypairName) && !"null".equalsIgnoreCase(keypairName)) {
            ServerKeypair serverKeypair = new ServerKeypair();
            Keypair keypair = keypairRepository.getByName(keyPairName, vendorId, server.getRegionId());
            if (null != keypair) {
                serverKeypair.setKeypairId(keypair.getId());
                serverKeypair.setServerId(server.getId());
                serverKeypairRepository.save(serverKeypair);
            }
        }
    }

}
