package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.loadbalance.LbDriver;
import com.bocloud.cmp.driver.network.ElasticIpDriver;
import com.bocloud.cmp.driver.network.ListenerDriver;
import com.bocloud.cmp.driver.network.NetworkCardDriver;
import com.bocloud.cmp.driver.network.PortDriver;
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.provider.utils.IPAddress;
import com.bocloud.common.enums.BoCloudExchange;
import com.bocloud.common.model.*;
import com.bocloud.common.model.OperateResult.OperateCategory;
import com.bocloud.common.model.RequestContext.Catalog;
import com.bocloud.common.utils.*;
import com.bocloud.ims.entity.common.Business;
import com.bocloud.ims.entity.common.Project;
import com.bocloud.ims.entity.common.Tenant;
import com.bocloud.ims.entity.common.User;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.LBAddBean;
import com.bocloud.ims.entity.resource.Ip.IpStatus;
import com.bocloud.ims.interfaces.resource.*;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.service.internal.SmsBusinessService;
import com.bocloud.ims.service.internal.SmsProjectService;
import com.bocloud.ims.service.internal.SmsTenantService;
import com.bocloud.ims.service.internal.SmsUserService;
import com.bocloud.ims.service.transporter.vendor.OpenstackTransporter;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
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.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 负载均衡器service实现
 *
 * @author wangyu
 * @version 1.0
 * @since 2017年9月4日
 */
@Service("loadBalancerService")
public class LoadBalancerServiceImpl implements LoadBalancerService {

    private static Logger logger = LoggerFactory.getLogger(LoadBalancerServiceImpl.class);
    private static OperateCategory operateCategory = OperateResult.OperateCategory.ResourceEvent;
    @Autowired
    private LoadBalancerRepository loadBalancerRepository;
    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private LbListenerRepository lbListenerRepository;
    @Autowired
    private LbPoolRepository lbPoolRepository;
    @Autowired
    private HealthMonitorRepository healthMonitorRepository;
    @Autowired
    private LbMemberRepository lbMemberRepository;
    @Autowired
    private SubnetRepository subnetRepository;
    @Autowired
    private IpRepository ipRepository;
    @Autowired
    private IpPoolRepository ipPoolRepository;
    @Autowired
    private PortRepository portRepository;
    @Autowired
    private LbDriver lbDriver;
    @Autowired
    private PortDriver portDriver;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private PortFixedIpRepository portFixedIpRepository;
    @Autowired
    private SmsProjectService smsProjectService;
    @Autowired
    private FloatingIpRepository floatingIpRepository;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private OSTenantRepository osTenantRepository;
    @Autowired
    private SecurityGroupRepository securityGroupRepository;
    @Autowired
    private ElasticIpRepository elasticIpRepository;
    @Autowired
    private VpcRepository vpcRepository;
    @Autowired
    private ElasticIpDriver elasticIpDriver;
    @Autowired
    private ElasticIpService elasticIpService;
    @Autowired
    private ListenerDriver listenerDriver;
    @Autowired
    private LbTargetGroupRepository lbTargetGroupRepository;
    @Autowired
    private NetworkInterfaceRepository networkInterfaceRepository;
    @Autowired
    private LbTargetRepository lbTargetRepository;
    @Autowired
    private CloudServerRepository cloudServerRepository;
    @Autowired
    private LbListenerService lbListenerService;
    @Autowired
    private LbTargetGroupService lbTargetGroupService;
    @Autowired
    private SmsUserService smsUserService;
    @Autowired
    private SmsBusinessService smsBusinessService;
    @Autowired
    private SmsTenantService smsTenantService;
    @Autowired
    private NetworkCardDriver networkCardDriver;
    @Autowired
    private NetworkCardRepository networkCardRepository;

    @Override
    public BocloudResult<GridBean<LoadBalancer>> list(Pager pager, RequestContext context) {
        GridBean gridBean = null;
        List<LoadBalancer> list = Lists.newArrayList();
        int total = 0;
        try {
            List<Param> params = Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>());
            Map<String, String> sorter = Optional.ofNullable(pager.getSorter()).orElse(Maps.newHashMap());
            Boolean simple = Optional.ofNullable(pager.getSimple()).orElse(false);
            sorter.put("gmtCreate", Common.ONE);
            Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
            Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);
            Long tenantId = context.getTenant();
            Long projectId = 0L;
            String vendorType = null;
            Long vendorId = null;
            for (Param param : params) {
                Map<String, Object> paramMap = param.getParam();
                if (paramMap.containsKey("vendorType")) {
                    vendorType = String.valueOf(paramMap.get("vendorType"));
                    paramMap.remove("vendorType");
                }
                if (paramMap.containsKey("vendorId")) {
                    vendorId = Long.valueOf(String.valueOf(paramMap.get("vendorId")));
                }
            }
            CloudVendor vendor = new CloudVendor();
            if (null != vendorId) {
                vendor = cloudVendorRepository.query(vendorId);
                Assert.notNull(vendor, "不存在此平台");
            }
            if (context.getCatalog().equals(Catalog.Tenant)) {
                // 租户能看到 1.属于当前租户的资源 2.租户下所有项目的资源
                List<Project> tenantProjects = smsProjectService.listTenantProjects(context.getTenant());
                List<Long> projectIds = tenantProjects.stream().map(Project::getId).collect(Collectors.toList());
                total = this.loadBalancerRepository.count(null, context.getTenant(), projectIds, params, vendorType);
                list = this.loadBalancerRepository.list(page, rows, null, context.getTenant(), projectIds, params,
                        sorter, vendorType);
                list = convertor(list);
                gridBean = new GridBean<>(page, rows, total, list);
            } else if (context.getCatalog().equals(Catalog.User)) {
                // 用户能看到 1.自己申请的资源 2.自己所在的资源可见项目（资源对项目下所有成员可见）下创建的资源 3.自己管理的项目下的资源
                List<Project> userManagerProjects = smsProjectService.listUserManagerProjects(context.getTarget());
                List<Project> visibleProjects = smsProjectService.listUserVisibleProjects(context.getTarget());
                List<Long> projectIds = new ArrayList<>();
                List<Long> userManagerProjectsIds =
                        userManagerProjects.stream().map(Project::getId).collect(Collectors.toList());
                if (!userManagerProjectsIds.isEmpty()) {
                    projectIds.addAll(userManagerProjectsIds);
                }
                List<Long> visibleProjectsIds =
                        visibleProjects.stream().map(Project::getId).collect(Collectors.toList());
                if (!visibleProjectsIds.isEmpty()) {
                    projectIds.addAll(visibleProjectsIds);
                }
                total = this.loadBalancerRepository.count(context.getTarget(), null, projectIds, params, vendorType);
                list = this.loadBalancerRepository.list(page, rows, context.getTarget(), null, projectIds, params,
                        sorter, vendorType);
                list = convertor(list);
                gridBean = new GridBean<>(page, rows, total, list);
            } else {
                total = loadBalancerRepository.count(params);
                if (simple) {
                    if (0L == context.getTenant()) {
                        params.add(new Param(MapTools.simpleMap(Common.TENANTID, 0), Sign.EQ));
                    }
                    List<SimpleBean> beans = loadBalancerRepository.list(params, sorter);
                    gridBean = new GridBean(1, 1, total, beans);
                } else {
                    if (!CloudProvider.VOLCENGINE.name().equals(vendor.getType())) {
                        list = this.loadBalancerRepository.list(page, rows, params, sorter);
                    } else {
                        list = loadBalancerRepository.listHaveEip(page, rows, params, sorter);
                    }
                    for (LoadBalancer balancer : list) {
                        params.clear();
                        params.add(new Param(MapTools.simpleMap("lbId", balancer.getId()), Sign.EQ));
                        int listenerNum = lbListenerRepository.count(params);
                        balancer.setListenerNum(listenerNum);
                        if (balancer.getAvailabilityZones() != null) {
                            balancer
                                    .setAvailabilityZones(JSONArray.parseArray(balancer.getAvailabilityZones().toString()));
                        }
                    }
                    gridBean = GridHelper.getBean(page, rows, total, list);
                }
            }
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("list load balancer failure:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    private List<LoadBalancer> convertor(List<LoadBalancer> list) {
        try {
            if (!ListTool.isEmpty(list)) {
                List<Long> tenantIds = new ArrayList<>();
                List<Long> userIds = new ArrayList<>();
                List<Long> businessIds = new ArrayList<>();
                List<Long> projectIds = new ArrayList<>();
                for (LoadBalancer boadBalancer : list) {
                    if (boadBalancer.getTenantId() != null) {
                        tenantIds.add(boadBalancer.getTenantId());
                    }
                    if (boadBalancer.getBusinessId() != null) {
                        businessIds.add(boadBalancer.getBusinessId());
                    }
                    if (boadBalancer.getProjectId() != null) {
                        projectIds.add(boadBalancer.getProjectId());
                    }
                    if (boadBalancer.getCreatorId() != null) {
                        userIds.add(boadBalancer.getCreatorId());
                    }
                    if (boadBalancer.getOwnerId() != null) {
                        userIds.add(boadBalancer.getOwnerId());
                    }
                    if (boadBalancer.getMenderId() != null) {
                        userIds.add(boadBalancer.getMenderId());
                    }
                }
                Map<Long, String> userMap = smsUserService.listUsersByIds(userIds).stream()
                        .collect(Collectors.toMap(User::getId, User::getName));
                Map<Long, String> projectMap = smsProjectService.listProjectsByIds(projectIds).stream()
                        .collect(Collectors.toMap(Project::getId, Project::getName));
                Map<Long, String> businessMap = smsBusinessService.listBusinesssByIds(businessIds).stream()
                        .collect(Collectors.toMap(Business::getId, Business::getName));
                Map<Long, String> tenantMap = smsTenantService.listTenantsByIds(tenantIds).stream()
                        .collect(Collectors.toMap(Tenant::getId, Tenant::getName));
                for (LoadBalancer boadBalancer : list) {
                    // 设置云主机归属信息
                    if (boadBalancer.getTenantId() != null) {
                        boadBalancer.setTenantName(tenantMap.get(boadBalancer.getTenantId()));
                    }
                    if (boadBalancer.getBusinessId() != null) {
                        boadBalancer.setBusinessName(businessMap.get(boadBalancer.getBusinessId()));
                    }
                    if (boadBalancer.getProjectId() != null) {
                        boadBalancer.setProjectName(projectMap.get(boadBalancer.getProjectId()));
                    }
                    if (boadBalancer.getCreatorId() != null) {
                        boadBalancer.setCreatorName(userMap.get(boadBalancer.getCreatorId()));
                    }
                    if (boadBalancer.getOwnerId() != null) {
                        boadBalancer.setOwnerName(userMap.get(boadBalancer.getOwnerId()));
                    }
                    if (boadBalancer.getMenderId() != null) {
                        boadBalancer.setMenderName(userMap.get(boadBalancer.getMenderId()));
                    }
                }
            }
        } catch (Exception e) {
            logger.error("获取基本信息异常：" + e.getMessage());
        }
        return list;

    }

    @Override
    public BocloudResult create(LBAddBean bean, RequestContext context, String callback) {
        try {
            LoadBalancer balancer =
                    JSONObject.parseObject(JSONObject.toJSONString(bean.getBalancer()), LoadBalancer.class);
            Long userId = context.getTarget();
            Long tenantId = 0L;
            if (context.getCatalog().equals(Catalog.Tenant) || context.getCatalog().equals(Catalog.User)) {
                tenantId = context.getTenant();
            }
            Long projectId = 0L;
            if (null == balancer) {
                return new BocloudResult<>(false, "参数设置有误");
            }
            Long vendorId = balancer.getVendorId();
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            if (null == vendor) {
                return new BocloudResult<>(false, "云平台不存在");
            }
            Long subnetId = balancer.getSubnetId();
            Subnet subnet = subnetRepository.query(subnetId);
            if (null == subnet) {
                return new BocloudResult<>(false, "子网不存在");
            }
            // 校验IP
            if (!StringUtils.isEmpty(balancer.getVipAddress())) {
                List<String> pools = JSONArray.parseArray(subnet.getIpPools(), String.class);
                if (ListTool.isEmpty(pools)) {
                    return new BocloudResult<>(false, "创建失败：该子网IP地址池分配有误");
                }
                IPAddress ipAddress = IPAddress.getIPAddress(balancer.getVipAddress());
                boolean flag = ipAddress.isInPools(balancer.getVipAddress(), pools);
                if (!flag) {
                    return new BocloudResult<>(false, "创建失败：该IP不在该子网的网段内");
                }
            }
            // 启动一个线程从MQ上获取数据
            final Long tenant = tenantId;
            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".lb";
                String content = "负载均衡器【" + balancer.getName() + "】创建失败";
                boolean success = true;
                try {
                    LbModel lbModel = new LbModel();
                    BeanUtils.copyProperties(balancer, lbModel);
                    lbModel.setSubnetUuid(subnet.getSubnetUuid());
                    BocloudResult result = null;
                    OSTenant osTenant = osTenantRepository.getByTenantId(context.getTenant(), vendor.getId());
                    if (null == osTenant) {
                        result = lbDriver.create(vendor.getUuid(), balancer.getOsTenantName(), null, lbModel);
                    } else {
                        result = lbDriver.create(vendor.getUuid(), osTenant.getName(), null, lbModel);
                    }
                    if (result.isFailed()) {
                        if (!StringUtils.isEmpty(balancer.getVipAddress())) {
                            ipRepository.delete(balancer.getVipAddress(), subnet.getId(), vendor.getId());
                        }
                        content += ":" + result.getMessage();
                        resourceEventPublisher.send(new OperateResult(false, content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                        success = false;
                    } else {
                        lbModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), LbModel.class);
                        BeanUtils.copyProperties(lbModel, balancer);
                        // 同步端口
                        result = portDriver.detail(balancer.getVipPortUuid(), vendor.getUuid(), null);
                        if (result.isFailed()) {
                            resourceEventPublisher.send(new OperateResult(true, content, operate,
                                    MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                        }
                        PortModel portModel =
                                JSONObject.parseObject(JSONObject.toJSONString(result.getData()), PortModel.class);
                        Port port = new Port();
                        BeanUtils.copyProperties(portModel, port);
                        port.preSave(userId, userId, vendorId, subnet.getNetworkId());
                        portRepository.save(port);

                        batchSavePortFixedIp(portModel.getPortFixedIps(), port.getPortUuid(), port.getId(),
                                vendorId);
                        // 创建负载均衡器
                        balancer.preSave(userId, userId, vendorId, subnetId, port.getId(), tenant, projectId);
                        loadBalancerRepository.save(balancer);
                        content = "负载均衡器【" + balancer.getName() + "】创建成功";
                        resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                    }
                } catch (Exception e) {
                    logger.error("Get Message Exception:", e);
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
                if (!StringUtils.isEmpty(callback)) {
                    BocloudResult bocloudResult = new BocloudResult<>(success, content);
                    if (success) {
                        bocloudResult.setData(balancer);
                    }
                    amqpTemplate.convertAndSend(callback, JSONObject.toJSON(bocloudResult));
                }
            }).start();
            return new BocloudResult<>(true, "创建任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("create load balancer fail:", e);
            return new BocloudResult<>(false, "创建失败");
        }
    }
    
    public boolean batchSavePortFixedIp(List<PortFixedIpModel> models, String portUuid, Long portId, Long vendorId)
            throws Exception {
        // 查出老的
        List<PortFixedIp> list = portFixedIpRepository.listByPortUuid(portUuid);
        Map<String, PortFixedIp> oldValues = new HashMap<>();
        for (PortFixedIp fixedIp : list) {
            if (oldValues.containsKey(fixedIp.getIpAddress())) {
                portFixedIpRepository.delete(fixedIp.getId());
            } else {
                oldValues.put(fixedIp.getIpAddress(), fixedIp);
            }
        }
        if (!ListTool.isEmpty(models)) {
            for (PortFixedIpModel model : models) {
                // 对象转换
                PortFixedIp fixedIp = new PortFixedIp();
                BeanUtils.copyProperties(model, fixedIp);
                if (fixedIp.getSubnetUuid() == null || fixedIp.getIpAddress() == null) {
                    continue;
                }
                Subnet subnet = subnetRepository.query(fixedIp.getSubnetUuid(), vendorId);
                if (null == subnet) {
                    continue;
                }
                fixedIp.setSubnetId(subnet.getId());
                if (oldValues.containsKey(fixedIp.getIpAddress())) {
                    // 没有修改 直接删掉就可以了
                    oldValues.remove(fixedIp.getIpAddress());
                } else {
                    fixedIp.setPortId(portId);
                    fixedIp.setPortUuid(portUuid);
                    portFixedIpRepository.save(fixedIp);
                }
            }
        }
        // 删除该删的
        for (Entry<String, PortFixedIp> entry : oldValues.entrySet()) {
            ipRepository.delete(entry.getValue().getIpAddress(), entry.getValue().getSubnetId(), vendorId);
            portFixedIpRepository.delete(entry.getValue().getId());
        }
        return true;
    }

    @Override
    public BocloudResult batchRemove(List<Long> idArray, RequestContext context) {
        if (ListTool.isEmpty(idArray)) {
            return new BocloudResult<>(false, "没有需要删除的负载均衡器！");
        }
        try {
            List<BocloudResult> succList = Lists.newArrayList();
            List<BocloudResult> failList = Lists.newArrayList();
            Long vendorId = null;
            for (Long id : idArray) {
                LoadBalancer loadBalancer = loadBalancerRepository.query(id);
                if (null != loadBalancer) {
                    if (null == vendorId) {
                        vendorId = loadBalancer.getVendorId();
                    }
                    BocloudResult result = remove(id, context);
                    if (result.isSuccess()) {
                        succList.add(new BocloudResult<>(true, "【" + loadBalancer.getName() + "】删除成功"));
                    } else {
                        failList.add(
                                new BocloudResult<>(false, "【" + loadBalancer.getName() + "】删除失败：" + result.getMessage()));
                    }
                }
            }
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            String operate = vendor.getType().toLowerCase() + ".lb";
            // 删除成功的数量
            int success = succList.size();
            // 删除失败的数量
            int fail = failList.size();
            String content = null;
            if (fail == idArray.size()) {
                content = "负载均衡器批量删除失败，详情如下：\n";
                for (BocloudResult bocloudResult : failList) {
                    content += bocloudResult.getMessage() + "\n";
                }
                resourceEventPublisher
                        .send(new OperateResult(false, content, operate, MapTools.simpleMap("vendorId", vendor.getId()),
                                OperateResult.OperateCategory.ResourceEvent, context));
            } else {
                content = "负载均衡器批量删除成功【" + success + "】个,失败【" + fail + "】个，详情如下：\n";
                for (BocloudResult bocloudResult : succList) {
                    content += bocloudResult.getMessage() + "\n";
                }
                for (BocloudResult bocloudResult : failList) {
                    content += bocloudResult.getMessage() + "\n";
                }
                resourceEventPublisher
                        .send(new OperateResult(true, content, operate, MapTools.simpleMap("vendorId", vendor.getId()),
                                OperateResult.OperateCategory.ResourceEvent, context));
            }
        } catch (Exception e) {
            logger.error("batch remove load balancer fail:", e);
            return new BocloudResult<>(false, "批量删除任务下发失败");
        }
        return new BocloudResult<>(true, "批量删除任务已下发，正在执行...");
    }

    @Override
    public BocloudResult create(LBAddBean bean, RequestContext context) {
        BocloudResult result;
        CloudVendor vendor = cloudVendorRepository.query(bean.getBalancer().getVendorId());
        if (null == vendor) {
            return new BocloudResult<>(false, "云平台不存在");
        }
        switch (CloudProvider.valueOf(vendor.getType())) {
            case AWS:
                result = createAWS(bean, context);
                break;
            case ALIYUN:
                result = createALIYUN(bean, context);
                break;
            case HUAWEI:
            case HCSO:
                result = createHUAWEI(bean, context);
                break;
            case VOLCENGINE:
                result = createVOLCENGINE(bean, context);
                break;
            default:
                result = createNormal(bean, context);
                break;
        }
        return result;
    }

    private BocloudResult createVOLCENGINE(LBAddBean bean, RequestContext context) {
        try {
            LoadBalancer balancer = bean.getBalancer();

            if (null == balancer) {
                return new BocloudResult<>(false, "参数设置有误");
            }
            String region = balancer.getRegion();

            String name = balancer.getName();
            // 网络类型 公网/私网 公网对应弹性公网ip
            // 绑定了弹性公网IP的为公网，否则为私网
            String balancerType = balancer.getLoadBalancerType();

            Long vpcId = balancer.getVpcId();

            Long subnetId = balancer.getSubnetId();

            if (null == region) {
                return new BocloudResult<>(false, "参数设置有误");
            }


            CloudVendor vendor = cloudVendorRepository.query(balancer.getVendorId());
            // 获取vpc及交换机
            Vpc vpc = vpcRepository.query(vpcId);
            if (null == vpc) {
                return new BocloudResult<>(false, "VPC资源不存在");
            }
            balancer.setVpcUuid(vpc.getVpcId());
            Subnet subnet = subnetRepository.query(subnetId);
            if (null == subnet) {
                return new BocloudResult<>(false, "虚拟交换机资源不存在");
            }
            Long vendorId = balancer.getVendorId();
            Long userId = context.getTarget();

            balancer.setSubnetUuid(subnet.getSubnetUuid());
            /* 启动一个线程从MQ上获取数据 */
            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".lb";
                String balanceName = StringUtils.isEmpty(balancer.getName()) ? "auto_named_slb" : balancer.getName();
                String content = "负载均衡器【" + balanceName + "】创建失败";
                try {
                    LbModel lbModel = new LbModel();
                    BeanUtils.copyProperties(balancer, lbModel);
                    lbModel.setRegionId(region);
                    if (StringUtils.isNotBlank(balancer.getEipType())) {
                        lbModel.setISP(balancer.getEipType());
                    }
                    BocloudResult result = lbDriver.create(vendor.getUuid(), region, lbModel);
                    if (result.isFailed()) {
                        NotifyMessage message = new NotifyMessage(context, "负载均衡器创建", content, true, false);
                        amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(), "event.notice.queue",
                                message);
                        resourceEventPublisher.send(new OperateResult(false, content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                        return;
                    }

                    LbModel model = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), LbModel.class);
                    com.bocloud.ims.service.utils.BeanUtils.copyPropertiesIgnoreNull(model, lbModel);
                    BeanUtils.copyProperties(lbModel, balancer);
                    // 与负载均衡绑定的弹性公网ip
                    if ("public".equalsIgnoreCase(balancerType)) {
                        BocloudResult eipDetail = elasticIpDriver.detail(model.getEipUuid(), vendor.getUuid(), region);
                        if (eipDetail.isFailed()) {
                            // 删除负载均衡
                            result = lbDriver.remove(balancer.getLbUuid(), vendor.getUuid(), region);
                            NotifyMessage message = new NotifyMessage(context, "负载均衡器-弹性公网IP创建", content, true, false);
                            amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(),
                                    "event.notice.queue", message);
                            return;
                        }
                        ElasticIp elasticIpNew = JSONObject.parseObject(JSONObject.toJSONString(eipDetail.getData()), ElasticIp.class);
                        if ("ClbInstance".equalsIgnoreCase(elasticIpNew.getInstanceType())) {
                            elasticIpNew.setBandwidthName(balancer.getName());
                            elasticIpNew.setVendorId(vendor.getId());
                            elasticIpNew.setRegionId(region);
                            elasticIpNew.setCreatorId(context.getTarget());
                            elasticIpRepository.save(elasticIpNew);
                        }
                        balancer.setEipId(elasticIpNew.getId());
                    }
                    // 与负载均衡绑定的网卡
                    BocloudResult networkDetail = networkCardDriver.detail(vendor.getUuid(), model.getNetworkCardUuid(), region);
                    if (networkDetail.isFailed()) {
                        // 删除负载均衡
                        result = lbDriver.remove(balancer.getLbUuid(), vendor.getUuid(), region);
                        NotifyMessage message = new NotifyMessage(context, "负载均衡器-网卡创建", content, true, false);
                        amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(),
                                "event.notice.queue", message);
                        return;
                    }
                    NetworkCardModel networkCardModel = JSONObject.parseObject(JSONObject.toJSONString(networkDetail.getData()), NetworkCardModel.class);
                    NetworkCard networkCard = new NetworkCard();
                    BeanUtils.copyProperties(networkCardModel, networkCard);
                    networkCard.setMenderId(userId);
                    networkCard.setRegionId(region);
                    networkCard.setCategory("LB");
                    networkCard.setGmtModify(new Date());
                    networkCard.setVendorId(vendorId);
                    networkCardRepository.save(networkCard);

                    balancer.setSubnetUuid(subnet.getSubnetUuid());
                    balancer.setVpcUuid(vpc.getVpcId());
                    balancer.setGmtCreate(new Date());
                    // 创建负载均衡器
                    balancer.setCreatorId(context.getTarget());
                    balancer.setVendorId(vendor.getId());
                    balancer.setRegion(region);
                    loadBalancerRepository.save(balancer);

                    content = "负载均衡器【" + balancer.getName() + "】创建成功";
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("Get Message Exception:", e);
                    lbDriver.remove(balancer.getLbUuid(), vendor.getUuid(), region);
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            }).start();
            return new BocloudResult<>(true, "创建任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("create load balancer fail:", e);
            return new BocloudResult<>(false, "创建失败");
        }
    }

    private BocloudResult createHUAWEI(LBAddBean bean, RequestContext context) {
        try {
            LoadBalancer balancer = bean.getBalancer();

            if (null == balancer) {
                return new BocloudResult<>(false, "参数设置有误");
            }

            JSONObject elasticIp = bean.getElasticIp();

            Long eipId = bean.getEipId();

            String region = balancer.getRegion();

            String name = balancer.getName();
            // 网络类型 公网/私网 公网对应弹性公网ip
            // 绑定了弹性公网IP的为公网，否则为私网
            String networkType = balancer.getNetworkType();

            Long vpcId = balancer.getVpcId();

            Long subnetId = balancer.getSubnetId();

            if (null == region) {
                return new BocloudResult<>(false, "参数设置有误");
            }
            CloudVendor vendor = cloudVendorRepository.query(balancer.getVendorId());
            // 获取vpc及交换机
            Vpc vpc = vpcRepository.query(vpcId);
            if (null == vpc) {
                return new BocloudResult<>(false, "VPC资源不存在");
            }
            balancer.setVpcUuid(vpc.getVpcId());
            Subnet subnet = subnetRepository.query(subnetId);
            if (null == subnet) {
                return new BocloudResult<>(false, "虚拟交换机资源不存在");
            }
            Long vendorId = balancer.getVendorId();
            Long userId = context.getTarget();

            balancer.setSubnetUuid(subnet.getSubnetUuid());
            balancer.setVipSubnetUuid(subnet.getNeutronSubnetUuid());
            /* 启动一个线程从MQ上获取数据 */
            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".lb";
                String balanceName = StringUtils.isEmpty(balancer.getName()) ? "auto_named_slb" : balancer.getName();
                String content =
                        "负载均衡器【" + balanceName + "】创建失败";
                try {
                    LbModel lbModel = new LbModel();
                    BeanUtils.copyProperties(balancer, lbModel);
                    lbModel.setRegionId(region);
                    // lbModel.setAvailabilityZones(availabilityZones);
                    BocloudResult result = lbDriver.create(vendor.getUuid(), region, lbModel);
                    if (result.isFailed()) {
                        NotifyMessage message = new NotifyMessage(context, "负载均衡器创建", content, true, false);
                        amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(), "event.notice.queue",
                                message);
                        resourceEventPublisher.send(new OperateResult(false, content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                        return;
                    }

                    LbModel model = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), LbModel.class);
                    com.bocloud.ims.service.utils.BeanUtils.copyPropertiesIgnoreNull(model, lbModel);
                    BeanUtils.copyProperties(lbModel, balancer);
                    // 同步端口
                    result = portDriver.detail(balancer.getVipPortUuid(), vendor.getUuid(), region);
                    if (result.isFailed()) {
                        resourceEventPublisher.send(new OperateResult(true, content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                        return;
                    }
                    PortModel portModel =
                            JSONObject.parseObject(JSONObject.toJSONString(result.getData()), PortModel.class);
                    Port port = new Port();
                    BeanUtils.copyProperties(portModel, port);
                    port.preSave(userId, userId, vendorId, subnet.getNetworkId());
                    portRepository.save(port);
                    // 与负载均衡绑定的弹性公网ip
                    ElasticIp elasticIpNew = null;
                    // 网络类型-公网，处理弹性ip信息
                    if (null != eipId && 0L != eipId) {
                        elasticIpNew = elasticIpRepository.query(eipId);
                    } else if (null != elasticIp) {
                        // 新建EIP
                        ElasticIpModel eipModel =
                                JSONObject.parseObject(elasticIp.toJSONString(), ElasticIpModel.class);
                        // BeanUtils.copyProperties(elasticIp, eipModel);
                        eipModel.setRegionId(balancer.getRegion());
                        if (StringUtils.isEmpty(eipModel.getBandwidthName())) {
                            eipModel.setBandwidthName(lbModel.getName() + "_eip");
                        }
                        BocloudResult eipResult = elasticIpDriver.allocate(eipModel, vendor.getUuid(), region);
                        if (eipResult.isFailed()) {
                            // 删除负载均衡
                            result = lbDriver.remove(balancer.getLbUuid(), vendor.getUuid(), region);
                            NotifyMessage message = new NotifyMessage(context, "负载均衡器-弹性公网IP创建", content, true, false);
                            amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(),
                                    "event.notice.queue", message);
                            return;
                        } else {
                            elasticIpNew =
                                    JSONObject.parseObject(JSONObject.toJSONString(eipResult.getData()), ElasticIp.class);
                            elasticIpNew.setVendorId(vendor.getId());
                            elasticIpNew.setCreatorId(context.getTarget());
                            elasticIpNew.setRegionId(balancer.getRegion());
                            elasticIpRepository.save(elasticIpNew);
                        }
                    }
                    if (null != elasticIpNew) {
                        // 弹性负载均衡与弹性公网ip绑定
                        ElasticIpGenericParam elasticIpGenericParam = new ElasticIpGenericParam();
                        elasticIpGenericParam.setId(elasticIpNew.getId());
                        elasticIpGenericParam.setInstanceId(balancer.getVipPortUuid());
                        elasticIpGenericParam.setAllowReassociation(false);
                        elasticIpGenericParam.setAction("bindLoadBalancer");
                        result = elasticIpService.associate(elasticIpGenericParam, context);
                        if (result.isFailed()) {
                            NotifyMessage message = new NotifyMessage(context, "负载均衡器与弹性公网ip绑定", content, true, false);
                            amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(),
                                    "event.notice.queue", message);
                            resourceEventPublisher.send(new OperateResult(false, content, operate,
                                    MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                            // return;
                        }
                    }
                    List<PortFixedIp> fixedIps = null;
                    // port对应的私网ip
                    List<PortFixedIpModel> fixedIpModels = portModel.getPortFixedIps();
                    if (!ListTool.isEmpty(fixedIpModels)) {
                        fixedIps = new ArrayList<>();
                        for (PortFixedIpModel fixedIpModel : fixedIpModels) {
                            PortFixedIp portFixedIp = new PortFixedIp();
                            BeanUtils.copyProperties(fixedIpModel, portFixedIp);
                            portFixedIp.setPortId(port.getId());
                            portFixedIp.setPortUuid(portModel.getPortUuid());
                            portFixedIp.setSubnetId(subnet.getId());
                            fixedIps.add(portFixedIp);
                        }
                        portFixedIpRepository.batchSave(fixedIps, 100);
                    }
                    balancer.setPortId(port.getId());
                    balancer.setSubnetUuid(subnet.getSubnetUuid());
                    balancer.setVpcUuid(vpc.getVpcId());

                    balancer.setGmtCreate(new Date());
                    // 创建负载均衡器
                    balancer.setCreatorId(context.getTarget());
                    balancer.setVendorId(vendor.getId());
                    balancer.setRegion(region);
                    loadBalancerRepository.save(balancer);

                    content = "负载均衡器【" + balancer.getName() + "】创建成功";
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("Get Message Exception:", e);
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            }).start();
            return new BocloudResult<>(true, "创建任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("create load balancer fail:", e);
            return new BocloudResult<>(false, "创建失败");
        }
    }

    private BocloudResult createALIYUN(LBAddBean bean, RequestContext context) {
        try {
            LoadBalancer balancer = bean.getBalancer();
            balancer.setLoadBalancerType(balancer.getScheme());
            Integer feeType = balancer.getFeeType();
            String region = balancer.getRegion();
            JSONArray availabilityZones = (JSONArray) balancer.getAvailabilityZones();
            JSONArray zones = (JSONArray) availabilityZones.clone();
            String spec = balancer.getSpec();
            String loadBalancerType = balancer.getLoadBalancerType();
            Long vpcId = balancer.getVpcId();
            Long subnetId = balancer.getSubnetId();
            String ipAddressType = balancer.getIpAddressType();

            if (null == availabilityZones || null == feeType || null == region || null == spec
                    || null == loadBalancerType || null == ipAddressType) {
                return new BocloudResult<>(false, "参数设置有误");
            }
            CloudVendor vendor = cloudVendorRepository.query(balancer.getVendorId());
            // 获取vpc及交换机
            if (null != vpcId) {
                Vpc vpc = vpcRepository.query(vpcId);
                if (null == vpc) {
                    return new BocloudResult<>(false, "VPC资源不存在");
                }
                balancer.setVpcUuid(vpc.getVpcId());
            }
            if (null != subnetId) {
                Subnet subnet = subnetRepository.query(subnetId);
                if (null == subnet) {
                    return new BocloudResult<>(false, "虚拟交换机资源不存在");
                }
                balancer.setSubnetUuid(subnet.getSubnetUuid());
            }
            // 获取资源组
            balancer.setResourceGroupUuid(balancer.getResourceGroupUuid());
            /* 启动一个线程从MQ上获取数据 */
            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".lb";
                String balanceName = StringUtils.isEmpty(balancer.getName()) ? "auto_named_slb" : balancer.getName();
                String content =
                        "负载均衡器【" + balanceName + "】创建失败";
                try {
                    LbModel lbModel = new LbModel();
                    BeanUtils.copyProperties(balancer, lbModel);
                    lbModel.setAvailabilityZones(availabilityZones);
                    BocloudResult result = null;
                    result = lbDriver.create(vendor.getUuid(), region, lbModel);
                    if (result.isFailed()) {
                        NotifyMessage message = new NotifyMessage(context, "负载均衡器创建", content, true, false);
                        amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(), "event.notice.queue",
                                message);
                        resourceEventPublisher.send(new OperateResult(false, content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                        return;
                    }
                    lbModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), LbModel.class);
                    BeanUtils.copyProperties(lbModel, balancer);
                    // 创建负载均衡器
                    balancer.setAvailabilityZones(zones.toJSONString());
                    balancer.setLoadBalancerType(balancer.getLoadBalancerType());
                    balancer.setInternetChargeType(balancer.getInternetChargeType());
                    balancer.setCreatorId(context.getTarget());
                    balancer.setVendorId(vendor.getId());
                    balancer.setProjectId(0L);
                    balancer.setTenantId(0L);
                    balancer.setRegion(region);
                    loadBalancerRepository.save(balancer);
                    content = "负载均衡器【" + balancer.getName() + "】创建成功";
                    NotifyMessage message = new NotifyMessage(context, "负载均衡器创建", content, true, false);
                    amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(), "event.notice.queue",
                            message);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("Get Message Exception:", e);
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            }).start();
            return new BocloudResult<>(true, "创建任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("create load balancer fail:", e);
            return new BocloudResult<>(false, "创建失败");
        }
    }

    public BocloudResult createNormal(LBAddBean bean, RequestContext context) {
        try {
            LoadBalancer balancer =
                    JSONObject.parseObject(JSONObject.toJSONString(bean.getBalancer()), LoadBalancer.class);
            LbListener listener = JSONObject.parseObject(JSONObject.toJSONString(bean.getListener()), LbListener.class);
            LbPool pool = JSONObject.parseObject(JSONObject.toJSONString(bean.getPool()), LbPool.class);
            Long userId = context.getTarget();
            Long tenantId = context.getTenant();
            Long projectId = context.getProject();
            HealthMonitor monitor =
                    JSONObject.parseObject(JSONObject.toJSONString(bean.getMonitor()), HealthMonitor.class);
            if (null == balancer || null == listener || null == pool || null == monitor) {
                return new BocloudResult<>(false, "参数设置有误");
            }
            Long vendorId = balancer.getVendorId();
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            if (null == vendor) {
                return new BocloudResult<>(false, "云平台不存在");
            }
            Long subnetId = balancer.getSubnetId();
            Subnet subnet = subnetRepository.query(subnetId);
            if (null == subnet) {
                return new BocloudResult<>(false, "子网不存在");
            }
            // 校验IP
            if (!StringUtils.isEmpty(balancer.getVipAddress())) {
                // 校验IP是否在子网范围内
                IpPool ipPool = ipPoolRepository.queryBySubnet(subnetId, subnet.getVendorId());
                if (null == ipPool) {
                    ipPool = new IpPool(subnet.getGateway(), subnet.getCidr(), subnet.getIpPools(),
                            subnet.getDnsNames(), subnetId, subnet.getNetworkId(), subnet.getVendorId());
                    ipPool.setCreatorId(context.getTarget());
                    ipPool.setMenderId(context.getTarget());
                    ipPool.setVersion(IPAddress.getVersion(subnet.getGateway()));
                    ipPoolRepository.save(ipPool);
                }
                List<String> pools = JSONArray.parseArray(ipPool.getPools(), String.class);
                if (ListTool.isEmpty(pools)) {
                    return new BocloudResult<>(false, "连接子网失败：该子网IP地址池分配有误");
                }
                IPAddress address = IPAddress.getIPAddress(balancer.getVipAddress());
                boolean flag = address.isInPools(balancer.getVipAddress(), pools);
                if (!flag) {
                    return new BocloudResult<>(false, "连接子网失败：该IP不在该子网的网段内");
                }
            }
            // 启动一个线程从MQ上获取数据
            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".lb";
                String content = "负载均衡器【" + balancer.getName() + "】创建失败";
                try {
                    LbModel lbModel = new LbModel();
                    BeanUtils.copyProperties(balancer, lbModel);
                    lbModel.setSubnetUuid(subnet.getSubnetUuid());
                    LbListenerModel listenerModel = new LbListenerModel();
                    BeanUtils.copyProperties(listener, listenerModel);
                    LbPoolModel poolModel = new LbPoolModel();
                    BeanUtils.copyProperties(pool, poolModel);
                    poolModel.setName(listener.getName() + "_pool");
                    HealthMonitorModel monitorModel = new HealthMonitorModel();
                    BeanUtils.copyProperties(monitor, monitorModel);
                    List<LbMember> members =
                            JSONArray.parseArray(JSONObject.toJSONString(bean.getMembers()), LbMember.class);
                    List<LbMemberModel> memberModels = Lists.newArrayList();
                    Map<String, Long> subnetMap = Maps.newHashMap();
                    if (!ListTool.isEmpty(members)) {
                        for (LbMember member : members) {
                            LbMemberModel memberModel = new LbMemberModel();
                            BeanUtils.copyProperties(member, memberModel);
                            memberModels.add(memberModel);
                            subnetMap.put(member.getSubnetUuid(), member.getSubnetId());
                        }
                    }
                    poolModel.setModel(monitorModel);
                    listenerModel.setPoolModel(poolModel);
                    listenerModel.setModels(memberModels);
                    List<LbListenerModel> listenerModels = Lists.newArrayList();
                    listenerModels.add(listenerModel);
                    lbModel.setModels(listenerModels);
                    BocloudResult result = null;
                    OSTenant osTenant = osTenantRepository.getByTenantId(context.getTenant(), vendor.getId());
                    if (null == osTenant) {
                        result = lbDriver.create(vendor.getUuid(), balancer.getOsTenantName(), null, lbModel);
                    } else {
                        result = lbDriver.create(vendor.getUuid(), osTenant.getName(), null, lbModel);
                    }
                    if (result.isFailed()) {
                        if (!StringUtils.isEmpty(balancer.getVipAddress())) {
                            ipRepository.delete(balancer.getVipAddress(), subnet.getId(), vendor.getId());
                        }
                        content += ":" + result.getMessage();
                        NotifyMessage message = new NotifyMessage(context, "负载均衡器创建", content, true, false);
                        amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(), "event.notice.queue",
                                message);
                        resourceEventPublisher.send(new OperateResult(false, content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                        return;
                    }
                    lbModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), LbModel.class);
                    BeanUtils.copyProperties(lbModel, balancer);
                    // 同步端口
                    result = portDriver.detail(balancer.getVipPortUuid(), vendor.getUuid(), null);
                    if (result.isFailed()) {
                        resourceEventPublisher.send(new OperateResult(true, content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                    }
                    PortModel portModel =
                            JSONObject.parseObject(JSONObject.toJSONString(result.getData()), PortModel.class);
                    Port port = new Port();
                    BeanUtils.copyProperties(portModel, port);
                    port.preSave(userId, userId, vendorId, subnet.getNetworkId());
                    portRepository.save(port);

                    batchSavePortFixedIp(portModel.getPortFixedIps(), port.getPortUuid(), port.getId(),
                            vendorId);
                    // 创建负载均衡器
                    balancer.preSave(userId, userId, vendorId, subnetId, port.getId(), tenantId, projectId);
                    loadBalancerRepository.save(balancer);
                    // 创建监听器
                    listenerModel = lbModel.getModels().get(0);
                    BeanUtils.copyProperties(listenerModel, listener);
                    listener.setLbUuid(balancer.getLbUuid());
                    listener.preSave(userId, userId, vendorId, balancer.getId(), tenantId, projectId);
                    lbListenerRepository.save(listener);
                    // 创建pool池
                    poolModel = listenerModel.getPoolModel();
                    BeanUtils.copyProperties(poolModel, pool);
                    pool.setListenerUuid(listener.getListenerUuid());
                    pool.preSave(userId, userId, vendorId, listener.getId(), tenantId, projectId);
                    lbPoolRepository.save(pool);
                    // 创建健康检查
                    monitorModel = poolModel.getModel();
                    BeanUtils.copyProperties(monitorModel, monitor);
                    monitor.setPoolUuid(pool.getPoolUuid());
                    monitor.preSave(userId, userId, vendorId, listener.getId(), pool.getId(), tenantId, projectId);
                    healthMonitorRepository.save(monitor);
                    // 创建成员
                    List<LbMemberModel> models = listenerModel.getModels();
                    if (!ListTool.isEmpty(models)) {
                        for (LbMemberModel model : models) {
                            LbMember member = new LbMember();
                            BeanUtils.copyProperties(model, member);
                            member.setName(model.getAddress());
                            member.preSave(userId, userId, vendorId, listener.getId(), pool.getId(),
                                    subnetMap.get(member.getSubnetUuid()), tenantId, projectId);
                            lbMemberRepository.save(member);
                        }
                    }
                    content = "负载均衡器【" + balancer.getName() + "】创建成功";
                    NotifyMessage message = new NotifyMessage(context, "负载均衡器创建", content, true, false);
                    amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(), "event.notice.queue",
                            message);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("Get Message Exception:", e);
                    content += e.getMessage();
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            }).start();
            return new BocloudResult<>(true, "创建任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("create load balancer fail:", e);
            return new BocloudResult<>(false, "创建失败");
        }

    }

    public BocloudResult createAWS(LBAddBean bean, RequestContext context) {
        try {
            LoadBalancer balancer = bean.getBalancer();
            List<LbListener> listeners = bean.getListeners();
            JSONArray availabilityZones = (JSONArray) balancer.getAvailabilityZones();
            JSONArray sgs = (JSONArray) balancer.getSecurityGroups();
            if (null == balancer || ListTool.isEmpty(listeners)
                    || (availabilityZones == null || availabilityZones.isEmpty())) {
                return new BocloudResult<>(false, "参数设置有误");
            }
            if ("application".equals(balancer.getLoadBalancerType())) {
                if (ListTool.isEmpty(sgs)) {
                    return new BocloudResult<>(false, "参数设置有误");
                }
                List<String> sgUuids = new ArrayList<>();
                for (Object sg : sgs) {
                    SecurityGroup securityGroup = securityGroupRepository.query(((JSONObject) sg).getLong("id"));
                    if (null == securityGroup) {
                        return new BocloudResult<>(false, "安全组不存在");
                    }
                    sgUuids.add(securityGroup.getGroupUuid());
                }
                balancer.setSecurityGroups(sgUuids);
            }

            Long vendorId = balancer.getVendorId();
            CloudVendor vendor = cloudVendorRepository.query(bean.getBalancer().getVendorId());

            for (Object object : availabilityZones) {
                JSONObject jsonObject = ((JSONObject) object);
                Long sId = jsonObject.getLong("sId");
                Subnet subnet = subnetRepository.query(sId);
                if (null == subnet) {
                    return new BocloudResult<>(false, "子网不存在");
                }
                jsonObject.put("subnetId", subnet.getSubnetUuid());

                JSONArray loadBalancerAddresses = jsonObject.getJSONArray("loadBalancerAddresses");
                if (loadBalancerAddresses != null) {
                    JSONObject loadBalancerAddress = loadBalancerAddresses.getJSONObject(0);
                    Long eipId = loadBalancerAddress.getLong("eipId");
                    if (eipId != null) {
                        ElasticIp elasticIp = elasticIpRepository.query(eipId);
                        if (null == elasticIp) {
                            return new BocloudResult<>(false, "弹性IP不存在");
                        }
                        loadBalancerAddress.put("allocationId", elasticIp.getElasticIpUuid());
                    }
                    String privateIPv4Address = loadBalancerAddress.getString("privateIPv4Address");
                    if (!StringUtils.isEmpty(privateIPv4Address)) {
                        loadBalancerAddress.put("privateIPv4Address", privateIPv4Address);
                    }
                    String iPv6Address = loadBalancerAddress.getString("iPv6Address");
                    if (!StringUtils.isEmpty(iPv6Address)) {
                        loadBalancerAddress.put("iPv6Address", iPv6Address);
                    }
                }
            }
            /* 启动一个线程从MQ上获取数据 */
            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".lb";
                String content = "负载均衡器【" + balancer.getName() + "】创建失败";
                try {
                    LbModel lbModel = new LbModel();
                    BeanUtils.copyProperties(balancer, lbModel);
                    lbModel.setAvailabilityZones(availabilityZones);
                    BocloudResult result = null;
                    result = lbDriver.create(vendor.getUuid(), balancer.getRegion(), lbModel);
                    if (result.isFailed()) {
                        NotifyMessage message = new NotifyMessage(context, "负载均衡器创建", content, true, false);
                        amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(), "event.notice.queue",
                                message);
                        resourceEventPublisher.send(new OperateResult(false, content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                        return;
                    }
                    lbModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), LbModel.class);
                    BeanUtils.copyProperties(lbModel, balancer);
                    // 创建负载均衡器
                    balancer.setAvailabilityZones(lbModel.getAvailabilityZones().toJSONString());
                    balancer.setSecurityGroups(JSONObject.toJSONString(lbModel.getSecurityGroups()));
                    balancer.setVpcId(vpcRepository.query(balancer.getVpcUuid(), vendorId).getId());
                    balancer.setCreatorId(context.getTarget());
                    balancer.setVendorId(vendorId);
                    balancer.setRegion(balancer.getRegion());
                    loadBalancerRepository.save(balancer);

                    // 创建目标群组
                    Long tgId = bean.getTargetGroup().getId();
                    if (tgId == null) {
                        result = lbTargetGroupService.create(bean.getTargetGroup(), context);
                        if (result.isFailed()) {
                            NotifyMessage message = new NotifyMessage(context, "目标群组创建", content, true, false);
                            amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(),
                                    "event.notice.queue", message);
                            resourceEventPublisher.send(new OperateResult(false, content, operate,
                                    MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                            return;
                        }
                        tgId = ((LbTargetGroup) result.getData()).getId();
                    }

                    // 创建监听器
                    for (LbListener lbListener : bean.getListeners()) {
                        lbListener.setLbId(balancer.getId());
                        lbListener
                                .setDefaultActions(JSONObject.parseArray("[{\"tgId\":" + tgId + ",\"type\":\"forward\"}]"));
                        bean.setListener(lbListener);
                        result = lbListenerService.create(bean, context, null);
                        if (result.isFailed()) {
                            content += ":" + result.getMessage();
                            NotifyMessage message = new NotifyMessage(context, "侦听器创建", content, true, false);
                            amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(),
                                    "event.notice.queue", message);
                            resourceEventPublisher.send(new OperateResult(false, content, operate,
                                    MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                            return;
                        }
                    }

                    content = "负载均衡器【" + balancer.getName() + "】创建成功";
                    NotifyMessage message = new NotifyMessage(context, "负载均衡器创建", content, true, false);
                    amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(), "event.notice.queue",
                            message);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));

                    Long startTime = System.currentTimeMillis();
                    Long endTime = System.currentTimeMillis();
                    while (endTime - startTime < 5 * 60 * 1000) {
                        // 创建时间不确定，增加休眠减少轮询次数
                        Thread.sleep(5000);
                        BocloudResult detailResult =
                                lbDriver.detail(balancer.getLbUuid(), vendor.getUuid(), balancer.getRegion());
                        if (detailResult.isSuccess()) {
                            lbModel = (LbModel) detailResult.getData();
                            if (!"provisioning".equals(lbModel.getStatus())) {
                                balancer.setStatus(lbModel.getStatus());
                                loadBalancerRepository.update(balancer);
                                break;
                            }
                        }
                        endTime = System.currentTimeMillis();
                    }
                } catch (Exception e) {
                    logger.error("Get Message Exception:", e);
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            }).start();
            return new BocloudResult<>(true, "创建任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("create load balancer fail:", e);
            return new BocloudResult<>(false, "创建失败");
        }
    }

    @Override
    public BocloudResult modify(Long id, LBAddBean bean, Long userId) {
        LoadBalancer balancer = bean.getBalancer();
        String path = LoadBalancer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            LoadBalancer lb = loadBalancerRepository.query(id);
            if (null == lb) {
                return new BocloudResult<>(false, "数据不存在");
            }
            CloudVendor vendor = cloudVendorRepository.query(lb.getVendorId());
            if (null == vendor) {
                return new BocloudResult<>(false, "云平台不存在");
            }
            LbModel model = new LbModel();
            BeanUtils.copyProperties(balancer, model);
            BocloudResult bocloudResult;
            switch (CloudProvider.valueOf(vendor.getType())) {
                case ALIYUN:
                    balancer.setRegion(lb.getRegion());
                    model.setLbUuid(lb.getLbUuid());
                    bocloudResult = lbDriver.update(vendor.getUuid(), balancer.getRegion(), model, bean.getAction());
                    break;
                case HUAWEI:
                case HCSO:
                    bocloudResult = lbDriver.update(vendor.getUuid(), balancer.getRegion(), model);
                    break;
                case VOLCENGINE:
                    model.setLbUuid(lb.getLbUuid());
                    if (null != balancer.getDeleteProtection()) {
                        if ("off".equalsIgnoreCase(balancer.getDeleteProtection())) {
                            model.setModificationProtection("NonProtection");
                            lb.setModificationProtection("NonProtection");
                        } else if ("on".equalsIgnoreCase(balancer.getDeleteProtection())) {
                            model.setModificationProtection("ConsoleProtection");
                            lb.setModificationProtection("ConsoleProtection");
                        }
                        lb.setDeleteProtection(balancer.getDeleteProtection());
                    }
                    bocloudResult = lbDriver.update(vendor.getUuid(), balancer.getRegion(), model);
                    break;
                default:
                    bocloudResult = lbDriver.update(vendor.getUuid(), null, model);
                    break;
            }
            if (bocloudResult.isFailed()) {
                return new BocloudResult<>(false, bocloudResult.getMessage());
            }

            switch (CloudProvider.valueOf(vendor.getType())) {
                case HUAWEI:
                case HCSO:
                    model = JSONObject.parseObject(JSONObject.toJSONString(bocloudResult.getData()), LbModel.class);
                    lb.setName(model.getName());
                    lb.setRemark(model.getRemark());
                    break;
                case ALIYUN:
                    if (null != balancer.getName()) {
                        lb.setName(balancer.getName());
                    }
                    if (null != balancer.getDeleteProtection()) {
                        lb.setDeleteProtection(balancer.getDeleteProtection());
                    }
                    if (null != balancer.getModificationProtection()) {
                        if ("ConsoleProtection".equalsIgnoreCase(balancer.getModificationProtection())) {
                            lb.setModificationProtection(balancer.getModificationProtection());
                            lb.setModificationProtection(balancer.getModificationProtection());
                        } else {
                            lb.setModificationProtection(balancer.getModificationProtection());
                            lb.setModificationProtection(null);
                        }
                    }
                    break;
                default:
                    model = JSONObject.parseObject(JSONObject.toJSONString(bocloudResult.getData()), LbModel.class);
                    model.setSubnetUuid(lb.getSubnetUuid());
                    BeanUtils.copyProperties(model, lb);
                    break;
            }
            lb.setMenderId(userId);
            lb.setGmtModify(new Date());
            // 更新负载均衡器本地记录
            loadBalancerRepository.update(lb);
            return new BocloudResult<>(true, "修改成功");
        } catch (Exception e) {
            logger.error("update load balancer fail:", e);
            return new BocloudResult<>(false, "修改失败");
        }
    }

    @Override
    public BocloudResult detail(Long id) {
        try {
            Long vendorId = loadBalancerRepository.getVendorId(id);
            if (null == vendorId) {
                return new BocloudResult<>(false, "负载均衡器不存在");
            }
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Assert.notNull(vendor, "不存在此平台");
            LoadBalancer balancer = null;
            if (!CloudProvider.VOLCENGINE.name().equals(vendor.getType())) {
                balancer = loadBalancerRepository.query(id);
            } else {
                balancer = loadBalancerRepository.queryHaveEip(id);
            }
            if (null == balancer) {
                return new BocloudResult<>(false, "负载均衡器不存在");
            }
            if (!StringUtils.isEmpty(balancer.getTenantUuid())) {
                OSTenant osTenant =
                        osTenantRepository.getByTenantUuid(balancer.getTenantUuid(), balancer.getVendorId());
                if (null != osTenant) {
                    balancer.setOsTenantName(osTenant.getName());
                }
            }
            List<LoadBalancer> balancers = new ArrayList<>();
            balancers.add(balancer);
            balancer = convertor(balancers).get(0);
            return new BocloudResult<>(true, balancer, "查询成功");
        } catch (Exception e) {
            logger.error("query load balancer fail:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult remove(Long id, RequestContext context) {
        try {
            LoadBalancer lb = loadBalancerRepository.query(id);
            if (null == lb) {
                return new BocloudResult<>(false, "数据不存在");
            }
            CloudVendor vendor = cloudVendorRepository.query(lb.getVendorId());
            if (null == vendor) {
                return new BocloudResult<>(false, "云平台不存在");
            }
            BocloudResult result;
            switch (CloudProvider.valueOf(vendor.getType())) {
                case AWS:
                    result = removeAWS(id, context);
                    break;
                case HUAWEI:
                case HCSO:
                    result = removeHUAWEI(id, context);
                    break;
                case ALIYUN:
                    result = removeALIYUN(id, context);
                    break;
                case VOLCENGINE:
                    result = removeVOLCENGINE(id, context);
                    break;
                default:
                    result = removeNormal(id, context);
                    break;
            }

            return result;

        } catch (Exception e) {
            logger.error("remove load balancer fail:", e);
            return new BocloudResult<>(false, "删除失败");
        }
    }

    private BocloudResult removeVOLCENGINE(Long id, RequestContext context) {
        String path = LoadBalancer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            LoadBalancer lb = loadBalancerRepository.query(id);
            if (null == lb) {
                return new BocloudResult<>(false, "数据不存在");
            }
            CloudVendor vendor = cloudVendorRepository.query(lb.getVendorId());
            if (null == vendor) {
                return new BocloudResult<>(false, "云平台不存在");
            }
            List<LbListener> listeners = lbListenerRepository.listByLbId(id);
            if (!CollectionUtils.isEmpty(listeners)) {
                return new BocloudResult<>(true, "该负载均衡器存在监听器，请先删除监听器");
            }
            List<LbPool> pools = lbPoolRepository.listByLbId(lb.getId());
            if (!CollectionUtils.isEmpty(pools)) {
                return new BocloudResult<>(true, "该负载均衡器存在后端服务器组，请先删除后端服务器组");
            }
            //由于平台没有对负载均衡和网卡的关系进行存储，所以删除时只有调用底层得到网卡Uuid
            BocloudResult detail = lbDriver.detail(lb.getLbUuid(), vendor.getUuid(), lb.getRegion());
            if (detail.isFailed()) {
                return new BocloudResult<>(false, detail.getMessage());
            }
            LbModel model = JSONObject.parseObject(JSONObject.toJSONString(detail.getData()), LbModel.class);
            BocloudResult result = lbDriver.remove(lb.getLbUuid(), vendor.getUuid(), lb.getRegion());
            if (result.isFailed()) {
                return new BocloudResult<>(false, result.getMessage());
            }
            if (null != lb.getEipId()) {
                ElasticIp elasticIp = elasticIpRepository.query(lb.getEipId());
                //说明是创建负载均衡时直接创建的公网ip
                if (elasticIp.getName().startsWith("clb-") && elasticIp.getName().endsWith("eip")) {
                    elasticIpRepository.remove(elasticIp.getId(), context.getTarget());
                }
            }
            //删除网卡
            networkCardRepository.removeByUuid(model.getNetworkCardUuid(), vendor.getId(), context.getTarget());

            // 删除本地负载均衡器记录
            loadBalancerRepository.remove(id, context.getTarget());

            return new BocloudResult<>(true, "删除成功");
        } catch (Exception e) {
            logger.error("remove load balancer fail:", e);
            return new BocloudResult<>(false, "删除失败");
        }
    }

    private BocloudResult removeALIYUN(Long id, RequestContext context) {
        String path = LoadBalancer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            LoadBalancer lb = loadBalancerRepository.query(id);
            if (null == lb) {
                return new BocloudResult<>(false, "数据不存在");
            }
            CloudVendor vendor = cloudVendorRepository.query(lb.getVendorId());
            if (null == vendor) {
                return new BocloudResult<>(false, "云平台不存在");
            }
            List<LbListener> listeners = lbListenerRepository.listByLbId(id);
            BocloudResult result = lbDriver.remove(lb.getLbUuid(), vendor.getUuid(), lb.getRegion());

            if (result.isFailed()) {
                return new BocloudResult<>(false, result.getMessage());
            }
            // 删除本地监听器记录
            lbListenerRepository.removeByLbId(id, context.getTarget());
            // 删除本地pool资源
            List<LbPool> pools = lbPoolRepository.listByLbId(id);
            lbPoolRepository.removeByLbId(id, context.getTarget());
            // 删除本地member资源
            for (LbPool pool : pools) {
                lbMemberRepository.removeByPoolId(pool.getId(), context.getTarget());
            }
            // 删除本地负载均衡器记录
            loadBalancerRepository.remove(id, context.getTarget());
            return new BocloudResult<>(true, "删除成功");
        } catch (Exception e) {
            logger.error("remove load balancer fail:", e);
            return new BocloudResult<>(false, "删除失败");
        }
    }

    public BocloudResult removeAWS(Long id, RequestContext context) {
        String path = LoadBalancer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            LoadBalancer lb = loadBalancerRepository.query(id);
            if (null == lb) {
                return new BocloudResult<>(false, "数据不存在");
            }
            CloudVendor vendor = cloudVendorRepository.query(lb.getVendorId());
            if (null == vendor) {
                return new BocloudResult<>(false, "云平台不存在");
            }
            List<LbListener> listeners = lbListenerRepository.listByLbId(id);
            if (listeners.size() > 1) {
                return new BocloudResult<>(true, "该负载均衡器存在一个以上的监听器");
            }
            if (listeners.size() == 1) {
                // 删除关联的监听器
                BocloudResult result = listenerDriver.remove(listeners.get(0).getListenerUuid(), vendor.getUuid(),
                        listeners.get(0).getRegionId());

                if (result.isFailed()) {
                    return new BocloudResult<>(false, "删除失败");
                }
            }
            BocloudResult result = lbDriver.remove(lb.getLbUuid(), vendor.getUuid(), null);

            if (result.isFailed()) {
                return new BocloudResult<>(false, result.getMessage());
            }
            Port port = portRepository.query(lb.getPortId());
            if (null != port) {
                // 更新端口绑定的浮动IP
                List<FloatingIp> fips = floatingIpRepository.listByPortId(port.getId());
                for (FloatingIp fip : fips) {
                    fip.setFixedIpAddress(null);
                    fip.setPortUuid(null);
                    fip.setPortId(null);
                    fip.setRouterUuid(null);
                    fip.setRouterId(null);
                    fip.setMenderId(context.getTarget());
                    fip.setStatus("STOPPED");
                    floatingIpRepository.update(fip);
                }
                List<PortFixedIp> fixedIps = portFixedIpRepository.listByPortId(port.getId());
                for (PortFixedIp fixedIp : fixedIps) {
                    // 回收IP
                    ipRepository.delete(fixedIp.getIpAddress(), fixedIp.getSubnetId(), lb.getVendorId());
                }
                portFixedIpRepository.deleteByPortId(port.getId());
                // 删除端口记录
                portRepository.remove(port.getId(), context.getTarget());
            }
            // 删除本地监听器记录
            if (listeners.size() == 1) {
                Long listenerId = listeners.get(0).getId();
                healthMonitorRepository.removeByListenerId(listenerId, context.getTarget());
                lbPoolRepository.removeByListenerId(listenerId, context.getTarget());
                lbMemberRepository.removeByListenerId(listenerId, context.getTarget());
                lbListenerRepository.remove(listenerId, context.getTarget());
            }
            // 删除本地负载均衡器记录
            loadBalancerRepository.remove(id, context.getTarget());
            // 删除负载均衡器关联的端口
            portRepository.removeByDeviceUuid(lb.getLbUuid(), context.getTarget(), vendor.getId());
            return new BocloudResult<>(true, "删除成功");
        } catch (Exception e) {
            logger.error("remove load balancer fail:", e);
            return new BocloudResult<>(false, "删除失败");
        }
    }

    public BocloudResult removeHUAWEI(Long id, RequestContext context) {
        String path = LoadBalancer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            LoadBalancer lb = loadBalancerRepository.query(id);
            if (null == lb) {
                return new BocloudResult<>(false, "数据不存在");
            }
            CloudVendor vendor = cloudVendorRepository.query(lb.getVendorId());
            if (null == vendor) {
                return new BocloudResult<>(false, "云平台不存在");
            }
            List<LbListener> listeners = lbListenerRepository.listByLbId(id);
            if (!CollectionUtils.isEmpty(listeners)) {
                return new BocloudResult<>(true, "该负载均衡器存在监听器，请先删除监听器");
            }
            List<LbPool> pools = lbPoolRepository.listByLbId(lb.getId());
            if (!CollectionUtils.isEmpty(pools)) {
                return new BocloudResult<>(true, "该负载均衡器存在后端服务器组，请先删除后端服务器组");
            }
            BocloudResult result = lbDriver.remove(lb.getLbUuid(), vendor.getUuid(), lb.getRegion());
            if (result.isFailed()) {
                return new BocloudResult<>(false, result.getMessage());
            }
            Port port = portRepository.query(lb.getPortId());
            if (null != port) {
                portFixedIpRepository.deleteByPortId(port.getId());
                // 删除端口记录
                portRepository.remove(port.getId(), context.getTarget());
                // 置空弹性公网ip绑定的关系
                List<ElasticIp> elasticIps = elasticIpRepository.listByIid(port.getPortUuid(), vendor.getId());
                if (!CollectionUtils.isEmpty(elasticIps)) {
                    for (ElasticIp elasticIp : elasticIps) {
                        elasticIp.setInstanceId(null);
                        elasticIp.setStatus("DOWN");
                        elasticIp.setAssociationId(null);
                        elasticIp.setGmtModify(new Date());
                        elasticIp.setMenderId(context.getTarget());
                    }
                    elasticIpRepository.batchUpdate(elasticIps, 100);
                }
            }

            // 删除本地负载均衡器记录
            loadBalancerRepository.remove(id, context.getTarget());
            // 删除负载均衡器关联的端口
            portRepository.removeByDeviceUuid(lb.getLbUuid(), context.getTarget(), vendor.getId());

            return new BocloudResult<>(true, "删除成功");
        } catch (Exception e) {
            logger.error("remove load balancer fail:", e);
            return new BocloudResult<>(false, "删除失败");
        }
    }

    public BocloudResult removeNormal(Long id, RequestContext context) {
        String path = LoadBalancer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            LoadBalancer lb = loadBalancerRepository.query(id);
            if (null == lb) {
                return new BocloudResult<>(false, "数据不存在");
            }
            if (0L == context.getTenant() && 0L != lb.getTenantId()) {
                return new BocloudResult<>(false, "不能删除租户下的负载均衡器");
            }
            CloudVendor vendor = cloudVendorRepository.query(lb.getVendorId());
            if (null == vendor) {
                return new BocloudResult<>(false, "云平台不存在");
            }
            List<LbListener> listeners = lbListenerRepository.listByLbId(id);
            if (listeners.size() > 1) {
                return new BocloudResult<>(true, "该负载均衡器存在一个以上的监听器");
            }
            if (listeners.size() == 1) {
                // 删除关联的监听器
                BocloudResult bocloudResult =
                        lbDriver.removeListener(vendor.getUuid(), null, listeners.get(0).getListenerUuid());
                if (bocloudResult.isFailed()) {
                    return new BocloudResult<>(false, "删除失败");
                }
            }
            BocloudResult result = lbDriver.remove(lb.getLbUuid(), vendor.getUuid(), null);
            if (result.isFailed()) {
                return new BocloudResult<>(false, result.getMessage());
            }
            Port port = portRepository.query(lb.getPortId());
            if (null != port) {
                // 更新端口绑定的浮动IP
                List<FloatingIp> fips = floatingIpRepository.listByPortId(port.getId());
                for (FloatingIp fip : fips) {
                    fip.setFixedIpAddress(null);
                    fip.setPortUuid(null);
                    fip.setPortId(null);
                    fip.setRouterUuid(null);
                    fip.setRouterId(null);
                    fip.setMenderId(context.getTarget());
                    fip.setStatus("STOPPED");
                    floatingIpRepository.update(fip);
                }
                List<PortFixedIp> fixedIps = portFixedIpRepository.listByPortId(port.getId());
                for (PortFixedIp fixedIp : fixedIps) {
                    // 回收IP
                    ipRepository.delete(fixedIp.getIpAddress(), fixedIp.getSubnetId(), lb.getVendorId());
                }
                portFixedIpRepository.deleteByPortId(port.getId());
                // 删除端口记录
                portRepository.remove(port.getId(), context.getTarget());
            }
            // 删除本地监听器记录
            healthMonitorRepository.removeByListenerId(id, context.getTarget());
            lbPoolRepository.removeByListenerId(id, context.getTarget());
            lbMemberRepository.removeByListenerId(id, context.getTarget());
            lbListenerRepository.remove(id, context.getTarget());
            // 删除本地负载均衡器记录
            loadBalancerRepository.remove(id, context.getTarget());
            // 删除负载均衡器关联的端口
            portRepository.removeByDeviceUuid(lb.getLbUuid(), context.getTarget(), vendor.getId());
            return new BocloudResult<>(true, "删除成功");
        } catch (Exception e) {
            logger.error("remove load balancer fail:", e);
            return new BocloudResult<>(false, "删除失败");
        }
    }

    @Override
    public JSONArray getElbByParams(String envCode, String appSystemCode) {
        JSONArray elbInfos = new JSONArray();
        try {
            JSONObject params = new JSONObject();
            params.put("envCode", envCode);
            params.put("appSystemCode", appSystemCode);
            List<LoadBalancer> loadBalancers = loadBalancerRepository.getByLabels(params.toJSONString());
            for (LoadBalancer loadBalancer : loadBalancers) {
                List<JSONObject> availabilityZones =
                        JSONArray.parseArray(loadBalancer.getAvailabilityZones().toString(), JSONObject.class);
                JSONArray lbIps = new JSONArray();
                String lbUuid = loadBalancer.getLbUuid();
                for (JSONObject availabilityZone : availabilityZones) {
                    Subnet subnet =
                            subnetRepository.getBySubId(availabilityZone.getString("subnetId"), loadBalancer.getVendorId());
                    if (null == subnet) {
                        continue;
                    }
                    List<NetworkInterface> networkInterfaces =
                            networkInterfaceRepository.listBysubnetId(loadBalancer.getVendorId(), subnet.getId());
                    for (NetworkInterface networkInterface : networkInterfaces) {
                        String remark = networkInterface.getRemark();
                        if (StringUtils.isEmpty(remark)
                                || !remark.contains(lbUuid.substring(lbUuid.indexOf(loadBalancer.getName())))) {
                            continue;
                        }
                        if (!StringUtils.isEmpty(networkInterface.getPublicIPAddress())) {
                            lbIps.add(networkInterface.getPublicIPAddress());
                        }
                        if (!StringUtils.isEmpty(networkInterface.getPrimaryPrivateIPAddress())) {
                            lbIps.add(networkInterface.getPrimaryPrivateIPAddress());
                        }
                    }
                }
                List<LbTargetGroup> targetGroups = lbTargetGroupRepository.queryByLbUuid(loadBalancer.getLbUuid());
                for (LbTargetGroup targetGroup : targetGroups) {
                    JSONObject elbInfo = new JSONObject();
                    elbInfo.put("lbId", loadBalancer.getId());
                    elbInfo.put("lbUuid", loadBalancer.getLbUuid());
                    elbInfo.put("lbName", loadBalancer.getName());
                    elbInfo.put("region", loadBalancer.getRegion());
                    elbInfo.put("lbIps", lbIps);
                    elbInfo.put("tgId", targetGroup.getId());
                    elbInfo.put("tgUuid", targetGroup.getUuid());
                    elbInfo.put("tgName", targetGroup.getName());
                    elbInfo.put("tgPort", targetGroup.getPort());
                    List<LbTarget> lbTargets = lbTargetRepository.list(targetGroup.getId());
                    List<JSONObject> targets = new ArrayList<JSONObject>();
                    for (LbTarget lbTarget : lbTargets) {
                        JSONObject target = new JSONObject();
                        if (lbTarget.getUuid().contains("i")) {
                            CloudServer server = cloudServerRepository.get(lbTarget.getUuid(), lbTarget.getVendorId());
                            if (null == server) {
                                continue;
                            }
                            target.put("address", JSONObject.parseArray(server.getPrivateIps(), String.class).get(0));
                        } else {
                            target.put("address", lbTarget.getUuid());
                        }
                        target.put("port", lbTarget.getPort());
                        targets.add(target);
                    }
                    elbInfo.put("targets", targets);
                    elbInfos.add(elbInfo);
                }
            }
        } catch (Exception e) {
            logger.error("ELB信息获取失败 {} ", e);
        }
        return elbInfos;
    }

    @Override
    public BocloudResult labels(Long id, String labels, RequestContext context) {
        String path = LoadBalancer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            LoadBalancer loadBalancer = loadBalancerRepository.query(id);
            loadBalancer.setLabels(labels);
            loadBalancer.setMenderId(context.getTarget());
            loadBalancer.setGmtModify(new Date());
            boolean result = loadBalancerRepository.update(loadBalancer);
            if (result) {
                return new BocloudResult(true, "负载均衡器标签成功");
            }
            return new BocloudResult(false, "负载均衡器标签失败");
        } catch (Exception e) {
            logger.error("负载均衡器标签失败 {}", e);
            return new BocloudResult(false, "负载均衡器标签失败");
        }
    }

    @Override
    public BocloudResult listAvailableLbs(Long vendorId, String regionId, RequestContext context) {
        try {
            List<LoadBalancer> listAvailableLbs = new ArrayList<>();
            List<LoadBalancer> availableLbs = new ArrayList<>();

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

    @Override
    public BocloudResult<Void> apply(ApplicationParam param) {
        try {
            Assert.notNull(param, "参数格式错误");
            ServiceOrder order = param.getOrder();
            Assert.notNull(order, "订单不存在");
            List<OrderItem> items = order.getItems();
            Assert.notEmpty(items, "订单明细不存在");
            // 申请人
            RequestContext context = param.getContext();
            Assert.notNull(context, "申请人不存在");
            // 位置
            LocationModel location = param.getLocation();
            // 订购信息
            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.OPENSTACK == provider || CloudProvider.EASYSTACK == provider) {
                OSTenant osTenant = osTenantRepository.getByTenantId(context.getTenant(), vendor.getId());
                Assert.notNull(osTenant, "租户云平台认证信息不存在");
            }
            logger.info("apply slb start...");
            for (int i = 0; i < count; i++) {
                OrderItem orderItem = items.get(i);
                switch (provider) {
                    case ALIYUN:
                        LoadBalancer balancer =
                                JSONObject.parseObject(param.getConfigs().toJSONString(), LoadBalancer.class);
                        String name = balancer.getName();
                        if (!StringUtils.isEmpty(name)) {
                            name = name + "_" + IDFactory.instance().uuid();
                        }
                        balancer.setLoadBalancerType(balancer.getScheme());
                        Integer feeType = balancer.getFeeType();
                        String region = balancer.getRegion() == null ? location.getRegion() : balancer.getRegion();
                        JSONArray availabilityZones = (JSONArray) balancer.getAvailabilityZones();
                        JSONArray zones = (JSONArray) availabilityZones.clone();
                        String spec = balancer.getSpec();
                        String loadBalancerType = balancer.getLoadBalancerType();
                        Long vpcId = balancer.getVpcId();
                        Long subnetId = balancer.getSubnetId();
                        String ipAddressType = balancer.getIpAddressType();

                        if (null == availabilityZones || null == feeType || null == region || null == spec
                                || null == loadBalancerType || null == ipAddressType) {
                            return new BocloudResult<>(false, "参数设置有误");
                        }
                        // 获取vpc及交换机
                        if (null != vpcId) {
                            Vpc vpc = vpcRepository.query(vpcId);
                            if (null == vpc) {
                                return new BocloudResult<>(false, "VPC资源不存在");
                            }
                            balancer.setVpcUuid(vpc.getVpcId());
                        }
                        if (null != subnetId) {
                            Subnet subnet = subnetRepository.query(subnetId);
                            if (null == subnet) {
                                return new BocloudResult<>(false, "虚拟交换机资源不存在");
                            }
                            balancer.setSubnetUuid(subnet.getSubnetUuid());
                        }
                        balancer.setResourceGroupUuid(balancer.getResourceGroupUuid());
                        try {
                            List<ResourceModel> resources = new ArrayList<>();
                            LbModel lbModel = new LbModel();
                            BeanUtils.copyProperties(balancer, lbModel);
                            lbModel.setAvailabilityZones(availabilityZones);
                            BocloudResult result = lbDriver.create(vendor.getUuid(), region, lbModel);
                            if (result.isFailed()) {
                                return new BocloudResult<>(false, "负载均衡申请失败：" + result.getMessage());
                            }
                            lbModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), LbModel.class);
                            BeanUtils.copyProperties(lbModel, balancer);
                            // 创建负载均衡器
                            balancer.setAvailabilityZones(zones.toJSONString());
                            balancer.setLoadBalancerType(balancer.getLoadBalancerType());
                            balancer.setInternetChargeType(balancer.getInternetChargeType());
                            balancer.setVendorId(vendor.getId());
                            balancer.setRegion(region);
                            balancer.setExpiredTime(calendar.getTime());
                            balancer.setUuid(orderItem.getSn());
                            // 自服务申请
                            balancer.setCreatorId(location.getCreatorId() == null ? 0 : location.getCreatorId());
                            balancer.setOwnerId(location.getOwnerId() == null ? 0 : location.getOwnerId());
                            balancer.setMenderId(location.getMenderId() == null ? 0 : location.getMenderId());
                            balancer.setCatalog(context.getCatalog());
                            balancer.setTenantId(context.getTenant() == null ? 0 : context.getTenant());
                            balancer.setBusinessId(location.getBusinessId() == null ? 0 : location.getBusinessId());
                            balancer.setProjectId(location.getProjectId() == null ? 0 : location.getProjectId());

                            loadBalancerRepository.save(balancer);
                            // 通知订单
                            OrderMessage message =
                                    new OrderMessage(orderItem.getSn(), OrderMessage.Operation.Application,
                                            OrderItemStatus.OpenedSuccess, null, "负载均衡申请创建成功", balancer.getGmtCreate(),
                                            calendar.getTime(), resources, ResourceCategory.LoadBalance.name(), context);
                            message.setCategory(ResourceCategory.LoadBalance.name());
                            // 通知订单
                            amqpTemplate.convertAndSend("resource.result.queue", message);
                        } catch (Exception e) {
                            logger.error("Get Message Exception:", e);
                            return new BocloudResult<>(false, "负载均衡申请失败：" + e.getMessage());
                        }
                        break;
                    case AWS:
                        LBAddBean bean = JSONObject.parseObject(param.getConfigs().toJSONString(), LBAddBean.class);
                        balancer = bean.getBalancer();
                        List<LbListener> listeners = bean.getListeners();
                        availabilityZones = (JSONArray) balancer.getAvailabilityZones();
                        JSONArray sgs = (JSONArray) balancer.getSecurityGroups();
                        if (null == balancer || ListTool.isEmpty(listeners)
                                || (availabilityZones == null || availabilityZones.isEmpty())) {
                            return new BocloudResult<>(false, "参数设置有误");
                        }
                        if ("application".equals(balancer.getLoadBalancerType())) {
                            if (ListTool.isEmpty(sgs)) {
                                return new BocloudResult<>(false, "参数设置有误");
                            }
                            List<String> sgUuids = new ArrayList<>();
                            for (Object sg : sgs) {
                                SecurityGroup securityGroup =
                                        securityGroupRepository.query(((JSONObject) sg).getLong("id"));
                                if (null == securityGroup) {
                                    return new BocloudResult<>(false, "安全组不存在");
                                }
                                sgUuids.add(securityGroup.getGroupUuid());
                            }
                            balancer.setSecurityGroups(sgUuids);
                        }

                        Long vendorId = vendor.getId();

                        for (Object object : availabilityZones) {
                            JSONObject jsonObject = ((JSONObject) object);
                            Long sId = jsonObject.getLong("sId");
                            Subnet subnet = subnetRepository.query(sId);
                            if (null == subnet) {
                                return new BocloudResult<>(false, "子网不存在");
                            }
                            jsonObject.put("subnetId", subnet.getSubnetUuid());

                            JSONArray loadBalancerAddresses = jsonObject.getJSONArray("loadBalancerAddresses");
                            if (loadBalancerAddresses != null) {
                                JSONObject loadBalancerAddress = loadBalancerAddresses.getJSONObject(0);
                                Long eipId = loadBalancerAddress.getLong("eipId");
                                if (eipId != null) {
                                    ElasticIp elasticIp = elasticIpRepository.query(eipId);
                                    if (null == elasticIp) {
                                        return new BocloudResult<>(false, "弹性IP不存在");
                                    }
                                    loadBalancerAddress.put("allocationId", elasticIp.getElasticIpUuid());
                                }
                                String privateIPv4Address = loadBalancerAddress.getString("privateIPv4Address");
                                if (!StringUtils.isEmpty(privateIPv4Address)) {
                                    loadBalancerAddress.put("privateIPv4Address", privateIPv4Address);
                                }
                                String iPv6Address = loadBalancerAddress.getString("iPv6Address");
                                if (!StringUtils.isEmpty(iPv6Address)) {
                                    loadBalancerAddress.put("iPv6Address", iPv6Address);
                                }
                            }
                        }

                        try {
                            List<ResourceModel> resources = new ArrayList<>();
                            LbModel lbModel = new LbModel();
                            BeanUtils.copyProperties(balancer, lbModel);
                            lbModel.setAvailabilityZones(availabilityZones);
                            BocloudResult result = null;
                            result = lbDriver.create(vendor.getUuid(), balancer.getRegion(), lbModel);
                            if (result.isFailed()) {
                                return new BocloudResult<>(false, "负载均衡申请失败：" + result.getMessage());
                            }
                            lbModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), LbModel.class);
                            BeanUtils.copyProperties(lbModel, balancer);
                            // 创建负载均衡器
                            balancer.setAvailabilityZones(lbModel.getAvailabilityZones().toJSONString());
                            balancer.setSecurityGroups(JSONObject.toJSONString(lbModel.getSecurityGroups()));
                            balancer.setVpcId(vpcRepository.query(balancer.getVpcUuid(), vendorId).getId());
                            balancer.setCreatorId(context.getTarget());
                            balancer.setVendorId(vendorId);
                            balancer.setRegion(location.getRegion());
                            balancer.setExpiredTime(calendar.getTime());
                            balancer.setUuid(orderItem.getSn());
                            // 自服务申请
                            balancer.setCreatorId(location.getCreatorId() == null ? 0 : location.getCreatorId());
                            balancer.setOwnerId(location.getOwnerId() == null ? 0 : location.getOwnerId());
                            balancer.setMenderId(location.getMenderId() == null ? 0 : location.getMenderId());
                            balancer.setCatalog(context.getCatalog());
                            balancer.setTenantId(context.getTenant() == null ? 0 : context.getTenant());
                            balancer.setBusinessId(location.getBusinessId() == null ? 0 : location.getBusinessId());
                            balancer.setProjectId(location.getProjectId() == null ? 0 : location.getProjectId());
                            loadBalancerRepository.save(balancer);

                            // 通知订单
                            OrderMessage message =
                                    new OrderMessage(orderItem.getSn(), OrderMessage.Operation.Application,
                                            OrderItemStatus.OpenedSuccess, null, "负载均衡申请创建成功", balancer.getGmtCreate(),
                                            calendar.getTime(), resources, ResourceCategory.LoadBalance.name(), context);
                            message.setCategory(ResourceCategory.LoadBalance.name());
                            // 通知订单
                            amqpTemplate.convertAndSend("resource.result.queue", message);

                            Long startTime = System.currentTimeMillis();
                            Long endTime = System.currentTimeMillis();
                            while (endTime - startTime < 5 * 60 * 1000) {
                                // 创建时间不确定，增加休眠减少轮询次数
                                Thread.sleep(5000);
                                BocloudResult detailResult =
                                        lbDriver.detail(balancer.getLbUuid(), vendor.getUuid(), balancer.getRegion());
                                if (detailResult.isSuccess()) {
                                    lbModel = (LbModel) detailResult.getData();
                                    if (!"provisioning".equals(lbModel.getStatus())) {
                                        balancer.setStatus(lbModel.getStatus());
                                        loadBalancerRepository.update(balancer);
                                        break;
                                    }
                                }
                                endTime = System.currentTimeMillis();
                            }
                        } catch (Exception e) {
                            logger.error("Get Message Exception:", e);
                            return new BocloudResult<>(false, "负载均衡申请失败：" + e.getMessage());
                        }
                        break;
                    default:
                        break;
                }
            }
            return new BocloudResult<>(true, "负载均衡器申请成功");
        } catch (Exception e) {
            logger.error("Apply slb error：{}", e.getMessage());
            return new BocloudResult<>(false, "负载均衡器申请失败：" + e.getMessage());
        }
    }

    @Override
    public BocloudResult extension(ExtensionParam param) {
        try {
            LoadBalancer balancer = loadBalancerRepository.getByUuid(param.getInstance());
            Assert.notNull(balancer, "负载均衡不存在");

            Calendar calendar = Calendar.getInstance();
            calendar.setTime(balancer.getExpiredTime());
            calendar.add(Calendar.MONTH, param.getExtension());
            balancer.setExpiredTime(calendar.getTime());
            loadBalancerRepository.update(balancer);

            OrderMessage message = new OrderMessage();
            message.setSn(param.getInstance());
            message.setOperation(Operation.Extension);
            message.setStatus(OrderItemStatus.ExtensionSuccess);
            message.setExtension(param.getExtension());
            message.setExpiredTime(calendar.getTime());
            message.setCategory(ResourceCategory.LoadBalance.name());
            message.setMessage("负载均衡延期成功");
            amqpTemplate.convertAndSend("resource.result.queue", message);
            return new BocloudResult<>(true, "负载均衡延期成功");
        } catch (Exception e) {
            logger.error("Get error message：{}", e);
            return new BocloudResult<>(false, e.getMessage());
        }
    }

    @Override
    public BocloudResult cancelation(CancelationParam param) {
        try {
            LoadBalancer balancer = loadBalancerRepository.getByUuid(param.getInstance());
            Assert.notNull(balancer, "负载均衡不存在");
            CloudVendor vendor = cloudVendorRepository.query(balancer.getVendorId());
            Assert.notNull(vendor, "云平台不存在！");
            RequestContext context = param.getContext();
            List<QuotaBean> quotas = new ArrayList<>();
            BocloudResult result = this.remove(balancer.getId(), context);
            Assert.isTrue(result.isSuccess(), result.getMessage());
            // network.aliyun.slb
            quotas.add(new QuotaBean("network" + vendor.getType().toLowerCase() + ".slb", 1));
            OrderMessage orderMessage = new OrderMessage(balancer.getUuid(), OrderMessage.Operation.Cancelation,
                    OrderItemStatus.UnsubscribeSuccess, null, "负载均衡退订成功", null, null, new ArrayList<>(),
                    ResourceCategory.LoadBalance.name(), context);
            orderMessage.setCategory(ResourceCategory.LoadBalance.name());
            orderMessage.setQuotas(quotas);
            amqpTemplate.convertAndSend("resource.result.queue", orderMessage);
            return new BocloudResult<>(true, "负载均衡退订成功");
        } catch (Exception e) {
            logger.error("Get error message：{}", e.getMessage());
            return new BocloudResult<>(false, e.getMessage());
        }
    }

}
