package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.common.HeatDriver;
import com.bocloud.cmp.driver.common.LocationDriver;
import com.bocloud.cmp.driver.compute.ServerDriver;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.*;
import com.bocloud.cmp.provider.utils.IPAddress;
import com.bocloud.common.enums.OSCategory;
import com.bocloud.common.enums.ResourceCatalog;
import com.bocloud.common.model.*;
import com.bocloud.common.utils.*;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.Ip.IpStatus;
import com.bocloud.ims.interfaces.resource.AutoScalingService;
import com.bocloud.ims.interfaces.resource.CloudStackService;
import com.bocloud.ims.interfaces.resource.IpService;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.service.transportor.OpenstackTransportor;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
import com.bocloud.ims.service.utils.YamlUtil;
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.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.yaml.snakeyaml.Yaml;

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

/**
 * 弹性伸缩
 *
 * @author 作者
 * @version 创建时间：2019年11月25日 下午7:16:05 类说明
 */
@Service("autoScalingService")
public class AutoScalingServiceImpl implements AutoScalingService {

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

    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private AutoScalingRepository autoScalingRepository;
    @Autowired
    private AutoScalingConfigRepository autoScalingConfigRepository;
    @Autowired
    private AutoScalingAlarmTaskRepository autoScalingAlarmTaskRepository;
    @Autowired
    private AutoScalingTimedTaskRepository autoScalingTimedTaskRepository;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private NetworkRepository networkRepository;
    @Autowired
    private ImageRepository imageRepository;
    @Autowired
    private FlavorRepository flavorRepository;
    @Autowired
    private HeatDriver heatDriver;
    @Autowired
    private KeypairRepository keypairRepository;
    @Autowired
    private CloudStackRepository cloudStackRepository;
    @Autowired
    private CloudStackService cloudStackService;
    @Autowired
    private ServerDriver serverDriver;
    @Autowired
    private RegionRepository regionRepository;
    @Autowired
    private ServerRepository serverRepository;
    @Autowired
    private PortRepository portRepository;
    @Autowired
    private PortFixedIpRepository portFixedIpRepository;
    @Autowired
    private IpRepository ipRepository;
    @Autowired
    private IpPoolRepository ipPoolRepository;
    @Autowired
    private SubnetRepository subnetRepository;
    @Autowired
    private CloudServerRepository cloudServerRepository;
    @Autowired
    private ResourceRepository resourceRepository;
    @Autowired
    private ServerSgroupRepository serverSgroupRepository;
    @Autowired
    private SecurityGroupRepository securityGroupRepository;
    @Autowired
    private OSTenantRepository osTenantRepository;
    @Autowired
    private LocationDriver locationDriver;
    @Autowired
    private LoadBalancerRepository loadBalancerRepository;
    @Autowired
    private LbListenerRepository lbListenerRepository;
    @Autowired
    private LbMemberRepository lbMemberRepository;
    @Autowired
    private LbPoolRepository lbPoolRepository;
    @Autowired
    private HealthMonitorRepository healthMonitorRepository;
    @Autowired
    private IpService ipService;

    @Override
    public BocloudResult<GridBean<AutoScalingConfig>> listAutoScalingConfig(Pager pager) {
        List<AutoScalingConfig> list = Lists.newArrayList();
        int total = 0;
        GridBean gridBean = null;
        try {
            pager.getSorter().put("gmtCreate", Common.ONE);
            total = autoScalingConfigRepository.count(pager.getParams());
            list = autoScalingConfigRepository.list(pager.getPage(), pager.getRows(), pager.getParams(), pager.getSorter());
            gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, list);
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("list autoscaling failure:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult<GridBean<AutoScaling>> listAutoScalingGroup(Pager pager) {
        List<AutoScaling> list = Lists.newArrayList();
        int total = 0;
        GridBean gridBean = null;
        try {
            pager.getSorter().put("gmtCreate", Common.ONE);
            total = autoScalingRepository.count(pager.getParams());
            list = autoScalingRepository.list(pager.getPage(), pager.getRows(), pager.getParams(), pager.getSorter());
            gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, list);
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("list autoscaling failure:", e);
            return new BocloudResult<>(false, "查询失败", null, null);
        }
    }

    @Override
    public BocloudResult<GridBean<AutoScalingAlarmTask>> listAlarmTask(Pager pager) {
        List<AutoScalingAlarmTask> list = Lists.newArrayList();
        int total = 0;
        GridBean gridBean = null;
        try {
            pager.getSorter().put("gmtCreate", Common.ONE);
            total = autoScalingAlarmTaskRepository.count(pager.getParams());
            list = autoScalingAlarmTaskRepository.list(pager.getPage(), pager.getRows(), pager.getParams(), pager.getSorter());
            gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, list);
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("list autoscaling failure:", e);
            return new BocloudResult<>(false, "查询失败", null, null);
        }
    }

    @Override
    public BocloudResult<GridBean<AutoScalingTimedTask>> listTimedTask(Pager pager) {
        List<AutoScalingTimedTask> list = Lists.newArrayList();
        int total = 0;
        GridBean gridBean = null;
        try {
            pager.getSorter().put("gmtCreate", Common.ONE);
            total = autoScalingTimedTaskRepository.count(pager.getParams());
            list = autoScalingTimedTaskRepository.list(pager.getPage(), pager.getRows(), pager.getParams(), pager.getSorter());
            gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, list);
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("list autoscaling failure:", e);
            return new BocloudResult<>(false, "查询失败", null, null);
        }
    }

    @Override
    public BocloudResult createAutoScaling(AutoScalingModel autoScalingModel, RequestContext requestContext) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(autoScalingModel.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            Network network = networkRepository.query(autoScalingModel.getNetworkId());
            Assert.notNull(network, "网络不存在！");
            List<Subnet> subnets = subnetRepository.listByNetworkUuid(network.getNetworkUuid(), vendor.getId());
            Assert.notEmpty(subnets, "当前网络下不存在子网，请重新选择！");
            AutoScalingConfig scalingConfig = autoScalingConfigRepository.query(autoScalingModel.getAutoScalingId());
            Assert.notNull(scalingConfig, "伸缩配置不允许为空！");
            Image image = imageRepository.getByImageUuid(scalingConfig.getImageUuid());
            Assert.notNull(image, "伸缩配置镜像信息异常！");
            Flavor flavor = flavorRepository.getByFlavorUuid(scalingConfig.getFlavorUuid());
            Assert.notNull(flavor, "伸缩配置规格信息异常！");
            Keypair keypair = keypairRepository.query(scalingConfig.getKeypairId());
            Assert.notNull(keypair, "伸缩配置秘钥信息异常！");
            Map<String, String> parameters = new HashMap<String, String>();
            parameters.put("keypair", keypair.getName());
            parameters.put("image", image.getName());
            parameters.put("flavor", flavor.getName());
            parameters.put("network", network.getNetworkUuid());
            parameters.put("max_size", autoScalingModel.getMaxSize() + "");
            parameters.put("min_size", autoScalingModel.getMinSize() + "");
            parameters.put("cooldown", autoScalingModel.getCooldown() + "");
            parameters.put("availability_zone", scalingConfig.getRegionId());
            Boolean useLb = autoScalingModel.getUseLb() == null ? false : autoScalingModel.getUseLb();
            // 创建伸缩组
            AutoScaling autoScaling = new AutoScaling();
            if (useLb) {
                Subnet subnet = subnetRepository.query(autoScalingModel.getSubnetId());
                Assert.notNull(subnet, "子网信息不存在！");
                parameters.put("subnet_id", subnet.getSubnetUuid());
                parameters.put("pool_protocol", autoScalingModel.getLbProtocol());
                parameters.put("listener_port", autoScalingModel.getLbPort().toString());
                autoScaling.setSubnetUuid(subnet.getSubnetUuid());
            }
            BeanUtils.copyProperties(autoScalingModel, autoScaling);
            String prefix = useLb ? "lb-" : "";
            autoScaling.setName("asg" + "-" + prefix + System.currentTimeMillis());
            autoScaling.setCreatorId(requestContext.getTarget());
            autoScaling.setUseLb(useLb);
            autoScaling.setMenderId(requestContext.getTarget());
            autoScaling.setAutoScalingConfigId(scalingConfig.getId());
            autoScaling.setNetworkUuid(network.getNetworkUuid());
            autoScaling.setStatus(BocloudStatus.Server.BUILDING.name());
            autoScalingRepository.save(autoScaling);
            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".alarmTask";
                String content = "伸缩组创建失败!";
                BocloudResult bocloudResult = new BocloudResult<>(false, content);
                String path = CloudVendor.class.getSimpleName() + "_" + vendor.getId();
                BocloudACLock lock = null;
                try {
                    lock = lockFactory.getACLock(path);
                    if (!lock.acquire(1, TimeUnit.MICROSECONDS)) {
                        logger.warn("Get harmonyLock time out!");
                        resourceEventPublisher.send(new OperateResult(bocloudResult.isSuccess(),
                                "当前云平台存在同步任务...请稍后再试！", operate, MapTools.simpleMap("vendorId", vendor.getId()),
                                OperateResult.OperateCategory.ResourceEvent, requestContext));
                        autoScalingRepository.remove(autoScaling.getId(), requestContext.getTarget());
                        return;
                    }
                    HeatStackModel heatStackModel = new HeatStackModel();
                    heatStackModel.setName(autoScaling.getName());
                    String readToString = "";
                    if (useLb) {
                        readToString = YamlUtil.readToString(StackConstants.LB_GROUP_TEMPLATE_FILENAME);
                        String lbEnv = YamlUtil.readToString(StackConstants.LB_ENV_FILENAME);
                        heatStackModel.setEnvironment(lbEnv);
                    } else {
                        readToString = YamlUtil.readToString(StackConstants.GROUP_TEMPLATE_FILENAME);
                    }
                    heatStackModel.setTemplate(readToString);
                    heatStackModel.setParameters(parameters);
                    String projectName = null;
                    OSTenant osTenant = osTenantRepository.getByTenantUuid(autoScalingModel.getTenantUuid(),
                            vendor.getId());
                    if (null != osTenant) {
                        projectName = osTenant.getName();
                    }
                    bocloudResult = heatDriver.createStack(heatStackModel, projectName, vendor.getUuid(), null);
                    if (bocloudResult.isSuccess()) {
                        HeatStackModel stackModel = (HeatStackModel) bocloudResult.getData();
                        CloudStack stack = new CloudStack();
                        BeanUtils.copyProperties(stackModel, stack);
                        stack.setCreatorId(requestContext.getTarget());
                        stack.setMenderId(requestContext.getTarget());
                        stack.setTenantUuid(autoScalingModel.getTenantUuid());
                        stack.setVendorId(vendor.getId());
                        stack.setTemplateParam(JSON.toJSONString(parameters));
                        cloudStackRepository.save(stack);
                        // 同步栈事件
                        cloudStackService.syncStackEvent(stackModel, vendor.getId(), stack.getId());
                        autoScaling.setStackId(stack.getId());
                        autoScaling.setResources(syncResource(stack));
                        autoScaling.setTemplate(stack.getTemplate());
                        autoScaling.setStatus(stack.getStatus());
                        autoScalingRepository.update(autoScaling);
                        syncResources(stack, vendor, requestContext);
                        if (autoScaling.getUseLb() == null ? false : autoScaling.getUseLb()) {
                            syncLoadBalancer(stack, vendor, requestContext, autoScaling);
                        }
                        content = "伸缩组创建成功！";
                    } else {
                        content = bocloudResult.getMessage();
                        autoScalingRepository.remove(autoScaling.getId(), requestContext.getTarget());
                    }
                } catch (Exception e) {
                    content = "伸缩组创建失败：" + e.getMessage();
                    try {
                        autoScalingRepository.remove(autoScaling.getId(), requestContext.getTarget());
                    } catch (Exception e1) {
                        logger.error("删除伸缩组失败：" + e1.getMessage());
                    }
                } finally {
                    if (null != lock) {
                        try {
                            lock.close();
                        } catch (Exception e) {
                        }
                    }
                }
                resourceEventPublisher.send(new OperateResult(bocloudResult.isSuccess(), content, operate,
                        MapTools.simpleMap("vendorId", vendor.getId()), OperateResult.OperateCategory.ResourceEvent,
                        requestContext));
            }).start();
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("Get error message:", e);
            return new BocloudResult<>(false, "创建失败");
        }
    }

    public String getPhysicalResourceId(List<JSONObject> jsonObjects, String resourceType) {
        if (null == jsonObjects || jsonObjects.isEmpty() || StringUtils.isEmpty(resourceType)) {
            return null;
        }
        for (JSONObject jsonObject : jsonObjects) {
            // 获取创建成功的虚机ID
            String type = jsonObject.getString("type");
            String resourceStatus = jsonObject.getString("resourceStatus");
            if (resourceType.equalsIgnoreCase(type) && "CREATE_COMPLETE".equalsIgnoreCase(resourceStatus)) {
                return jsonObject.getString("physicalResourceId");
            }
        }
        return null;
    }

    public BocloudResult syncLoadBalancer(CloudStack cloudStack, CloudVendor vendor, RequestContext requestContext,
                                          AutoScaling autoScaling) {
        try {
            String resources = cloudStack.getResources();
            Assert.notNull(resources, "resources 资源为空！");
            List<JSONObject> parseArray = JSON.parseArray(resources, JSONObject.class);
            String defaultPoolUuid = getPhysicalResourceId(parseArray, "OS::Neutron::LBaaS::Pool");
            String lbUuid = getPhysicalResourceId(parseArray, "OS::Neutron::LBaaS::LoadBalancer");
            String listenerUuid = getPhysicalResourceId(parseArray, "OS::Neutron::LBaaS::Listener");
            LbListenerModel lbListenerModel = new LbListenerModel();
            lbListenerModel.setDefaultPoolUuid(defaultPoolUuid);
            lbListenerModel.setLbUuid(lbUuid);
            lbListenerModel.setListenerUuid(listenerUuid);
            BocloudResult syncStack = locationDriver.syncStack(vendor.getUuid(), lbListenerModel);
            OpenstackTransportor toolOS = new OpenstackTransportor(networkRepository, subnetRepository, portRepository,
                    ipRepository, loadBalancerRepository, lbListenerRepository, lbMemberRepository, lbPoolRepository,
                    healthMonitorRepository, portFixedIpRepository, ipPoolRepository, ipService);
            BocloudResult bocloudResult = toolOS.syncStack(vendor, syncStack.getData(), requestContext.getTarget());
            if (bocloudResult.isSuccess()) {
                LoadBalancer loadBalancer = loadBalancerRepository.queryByUuid(lbUuid, vendor.getId());
                if (null != loadBalancer) {
                    List<LbListener> listByLbId = lbListenerRepository.listByLbId(loadBalancer.getId());
                    if (null != listByLbId && !listByLbId.isEmpty()) {
                        LbListener lbListener = listByLbId.get(0);
                        LbPool lbPool = lbPoolRepository.getByListenerId(lbListener.getId());
                        autoScaling.setLbId(loadBalancer.getId());
                        autoScaling.setLbListenerId(lbListener.getId());
                        autoScaling.setPoolId(lbPool.getId());
                    }
                    autoScalingRepository.update(autoScaling);
                }
                logger.info("负载均衡同步完成...");
                return new BocloudResult<>(true, "负载均衡同步成功！");
            } else {
                logger.info("负载均衡同步异常！" + bocloudResult.getMessage());
                return new BocloudResult<>(false, "负载均衡同步异常！");
            }
        } catch (Exception e) {
            return new BocloudResult<>(false, "同步负载均衡异常:" + e.getMessage());
        }
    }

    private String syncResource(CloudStack cloudStack) throws Exception {
        try {
            String resources = cloudStack.getResources();
            Assert.notNull(resources, "resources 资源为空！");
            List<JSONObject> parseArray = JSON.parseArray(resources, JSONObject.class);
            return JSON.toJSONString(parseArray.stream()
                    .filter(item -> !StackConstants.SERVER_RESOURCE_TYPE.equalsIgnoreCase(item.getString("type"))
                            && !StackConstants.LB_ENV_FILENAME.equalsIgnoreCase(item.getString("type")))
                    .collect(Collectors.toList()));
        } catch (Exception e) {
            logger.error("异常： " + e.getMessage());
            return null;
        }
    }

    @SuppressWarnings("unchecked")
    public void syncResources(CloudStack cloudStack, CloudVendor vendor, RequestContext requestContext) {
        try {
            HeatStackModel stackModel = new HeatStackModel();
            stackModel.setStackUuid(cloudStack.getStackUuid());
            BocloudResult listByStack = serverDriver.listByStack(stackModel, vendor.getUuid(), null);
            List<ServerModel> serverModels = new ArrayList<>();
            if (listByStack.isSuccess()) {
                serverModels = (List<ServerModel>) listByStack.getData();
            }
            if (!serverModels.isEmpty()) {
                for (ServerModel serverModel : serverModels) {
                    CloudServer cloudServer = cloudServerRepository.getByInstanceId(serverModel.getInstanceId(),
                            vendor.getId());
                    if (null == cloudServer) {
                        sycnServers(serverModel, vendor, requestContext, cloudStack.getId());
                    } else {
                        cloudServer.setEnv(cloudStack.getId());
                        cloudServerRepository.update(cloudServer);
                    }
                }
            } else {
                cloudServerRepository.removeByEnv(cloudStack.getId(), vendor.getId(), requestContext.getTarget());
            }
        } catch (Exception e) {
            logger.error("同步资源异常：" + e.getMessage());
        }
    }

    private void sycnServers(ServerModel serverModel, CloudVendor vendor, RequestContext requestContext, Long stackId) {
        try {
            Long userId = requestContext.getTarget();
            String content = JSONObject.toJSONString(serverModel);
            CloudServer server = JSONObject.parseObject(content, CloudServer.class);
            Region region = regionRepository.getByName(server.getZone(), vendor.getId());
            if (null != region) {
                server.setRegion(region.getName());
            }
            server.setEnv(stackId);
            server.setVendorId(vendor.getId());
            server.setCreatorId(requestContext.getTarget());
            server.setIsTemplate(false);
            server.setVendorType(vendor.getType());
            server.setRecycle(false);
            server.setProjectId(0L);
            server.setTenantId(0L);
            server.setMenderId(requestContext.getTarget());
            String hostName = server.getHostName();
            if (null != hostName) {
                server.setHostName(hostName);
                Server host = serverRepository.getByName(hostName, vendor.getId());
                if (null != host) {
                    server.setHostId(host.getId());
                }
            }
            server.setManagerIp(server.getManagerIp());
            String state = server.getStatus();
            if (BocloudStatus.Server.ERROR.name().equalsIgnoreCase(state)) {
                server.setStatus(BocloudStatus.Server.EXCEPTION.name());
            }
            List<PortModel> ports = server.getPorts();
            // 保存端口
            Map<String, List<PortModel>> portMap = Maps.newHashMap();
            Map<String, NetworkBean> networkMap = Maps.newHashMap();
            Map<String, AddressBean> subnetMap = Maps.newHashMap();
            for (PortModel portModel : ports) {
                Port port = new Port();
                BeanUtils.copyProperties(portModel, port);
                Network network = networkRepository.getByNetId(portModel.getNetworkUuid());
                NetworkBean networkBean = new NetworkBean(network.getId(), network.getName(), network.getNetworkUuid());
                networkMap.put(portModel.getNetworkUuid(), networkBean);
                port.preSave(userId, userId, vendor.getId(), network.getId());
                port.setStatus(BocloudStatus.Network.RUNNING.name());
                port.setDeviceOwner("compute:None");
                port.setDeviceUuid(server.getInstanceId());
                portRepository.save(port);
                // 保存fixedip
                List<PortFixedIpModel> fixedIpModels = portModel.getPortFixedIps();
                if (!ListTool.isEmpty(fixedIpModels)) {
                    for (PortFixedIpModel fixedIpModel : fixedIpModels) {
                        PortFixedIp portFixedIp = new PortFixedIp();
                        BeanUtils.copyProperties(fixedIpModel, portFixedIp);
                        portFixedIp.setPortId(port.getId());
                        portFixedIp.setPortUuid(portModel.getPortUuid());
                        Subnet subnet = subnetRepository.getBySubId(fixedIpModel.getSubnetUuid());
                        if (null != subnet) {
                            portFixedIp.setSubnetId(subnet.getId());
                        }
                        portFixedIpRepository.save(portFixedIp);
                        AddressBean addressBean = new AddressBean(subnet.getId(), subnet.getName(), network.getId(),
                                subnet.getSubnetUuid(), port.getId(), port.getPortUuid(), portFixedIp.getIpAddress());
                        subnetMap.put(addressBean.getSubnetUuid(), addressBean);
                        // 更新IP
                        Ip ip = ipRepository.checkExist(fixedIpModel.getIpAddress(), subnet.getId(), vendor.getId());
                        // IP不存在，则添加IP记录
                        if (null == ip) {
                            String mask = IPAddress.getIPAddress(fixedIpModel.getIpAddress()).getMask(subnet.getCidr());
                            ip = new Ip(fixedIpModel.getIpAddress(), mask, subnet.getGateway(), subnet.getDnsNames(),
                                    vendor.getId(), IDFactory.instance().uuid(), null, IpStatus.used);
                            ip.setSubnetId(subnet.getId());
                            ip.setNetworkId(port.getNetworkId());
                            ip.setCatalog("PORT");
                            ip.setTarget(port.getId());
                            IpPool pool = ipPoolRepository.queryBySubnet(subnet.getId(), vendor.getId());
                            if (null != pool) {
                                ip.setPoolId(pool.getId());
                            }
                            ipRepository.save(ip);
                        } else {
                            ip.setTarget(port.getId());
                            ipRepository.update(ip);
                        }
                    }
                }
                portModel.setPortId(port.getId());
                if (portMap.containsKey(portModel.getNetworkUuid())) {
                    List<PortModel> models = portMap.get(portModel.getNetworkUuid());
                    models.add(portModel);
                } else {
                    List<PortModel> models = Lists.newArrayList();
                    models.add(portModel);
                    portMap.put(portModel.getNetworkUuid(), models);
                }
            }
            List<NetworkBean> beans = Lists.newArrayList();
            for (String key : portMap.keySet()) {
                List<PortModel> portList = portMap.get(key);
                if (!portList.isEmpty()) {
                    NetworkBean networkBean = networkMap.get(key);
                    List<AddressBean> addresses = Lists.newArrayList();
                    for (PortModel pModel : portList) {
                        AddressBean address = subnetMap.get(pModel.getPortFixedIps().get(0).getSubnetUuid());
                        address.setAddress(pModel.getPortFixedIps().get(0).getIpAddress());
                        address.setPortId(pModel.getPortId());
                        address.setPortUuid(pModel.getPortUuid());
                        addresses.add(address);
                    }
                    networkBean.setAddresses(addresses);
                    beans.add(networkBean);
                }
            }
            // 设置内网所有ip
            server.setPrivateIps(JSONObject.toJSONString(beans));
            Image image = imageRepository.getByImageUuid(server.getImageUuid());
            String osCategory = image.getOsCategory();
            if ("linux".equalsIgnoreCase(osCategory)) {
                osCategory = OSCategory.LINUX.name();
            } else if ("windows".equalsIgnoreCase(osCategory)) {
                osCategory = OSCategory.WINDOWS.name();
            } else if ("unix".equalsIgnoreCase(osCategory)) {
                osCategory = OSCategory.UNIX.name();
            } else if ("aix".equalsIgnoreCase(osCategory)) {
                osCategory = OSCategory.AIX.name();
            } else {
                osCategory = OSCategory.LINUX.name();
            }
            server.setOsCategory(osCategory);
            cloudServerRepository.save(server);
            // 保存安全组信息
            if (!StringUtils.isEmpty(server.getGroups())) {
                logger.info("Start to sync vm security group...");
                // 删除旧安全组与虚拟机的关系
                serverSgroupRepository.removeBySid(server.getId());
                List<String> groups = JSONObject.parseArray(server.getGroups(), String.class);
                for (String group : groups) {
                    SecurityGroup securityGroup = securityGroupRepository.getByName(group, server.getTenantUuid());
                    if (null != securityGroup) {
                        // 保存虚拟机和安全组关系
                        serverSgroupRepository.save(new ServerSgroup(server.getId(), securityGroup.getId()));
                    }
                }
                logger.info("End to sync vm security group...");
            }
            // 保存资源
            List<String> ips = Lists.newArrayList();
            if (!StringUtils.isEmpty(server.getPrivateIps())) {
                List<JSONObject> objects = JSONObject.parseArray(server.getPrivateIps(), JSONObject.class);
                for (JSONObject object : objects) {
                    List<Object> addresses = object.getJSONArray("addresses");
                    for (Object address : addresses) {
                        if (StringUtils.isEmpty(
                                JSONObject.parseObject(JSONObject.toJSONString(address)).getString("address"))) {
                            continue;
                        }
                        ips.add(JSONObject.parseObject(JSONObject.toJSONString(address)).getString("address"));
                    }
                }
            }
            Resource resource = resourceRepository.query(ResourceCategory.Computer.name(),
                    ResourceCatalog.LOGICAL.name(), server.getId());
            if (null == resource) {
                resource = new Resource(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
                        server.getId(), JSONObject.toJSONString(ips), server.getOsCategory(), vendor.getId());
                resource.preSave(server.getName(), server.getStatus(), userId, requestContext.getTenant(),
                        requestContext.getProject());
                resource.setInventory(JSONObject.toJSONString(server));
                resourceRepository.save(resource);
            } else {
                resource.setInventory(JSONObject.toJSONString(server));
                resource.setStatus(server.getStatus());
                resource.setMenderId(userId);
                resource.setCreatorId(userId);
                resource.setGmtModify(new Date());
                resource.setGmtCreate(new Date());
                resource.setPrivateIps(JSONObject.toJSONString(ips));
                resourceRepository.update(resource);
            }
        } catch (Exception e) {
            logger.error("同步异常：" + e.getMessage());
        }
    }

    @Override
    public BocloudResult modifyAutoScaling(AutoScaling autoScaling, RequestContext requestContext) {
        try {
            AutoScaling oldAutoScaling = autoScalingRepository.query(autoScaling.getId());
            Assert.notNull(oldAutoScaling, "伸缩组数据异常！");
            CloudVendor vendor = cloudVendorRepository.query(oldAutoScaling.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            CloudStack cloudStack = cloudStackRepository.query(oldAutoScaling.getStackId());
            Assert.notNull(cloudStack, "栈信息异常！");
            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".alarmTask";
                String content = "伸缩组编辑失败!";
                BocloudResult bocloudResult = new BocloudResult<>(false, content);
                String path = AutoScaling.class.getSimpleName() + "_" + autoScaling.getId();
                BocloudACLock lock = null;
                try {
                    lock = lockFactory.getACLock(path);
                    if (!lock.acquire(1, TimeUnit.MICROSECONDS)) {
                        logger.warn("Get harmonyLock time out!");
                        resourceEventPublisher.send(new OperateResult(bocloudResult.isSuccess(),
                                "当前资源存在任务...请稍后再试！", operate, MapTools.simpleMap("vendorId", vendor.getId()),
                                OperateResult.OperateCategory.ResourceEvent, requestContext));

                        return;
                    }
                    String template = cloudStack.getTemplate();
                    HeatStackModel heatStackModel = new HeatStackModel();
                    heatStackModel.setName(cloudStack.getName());
                    heatStackModel.setTemplate(template);
                    heatStackModel.setStackUuid(cloudStack.getStackUuid());
                    String templateParam = cloudStack.getTemplateParam();
                    if (oldAutoScaling.getUseLb() == null ? false : oldAutoScaling.getUseLb()) {
                        String lbEnv = YamlUtil.readToString(StackConstants.LB_ENV_FILENAME);
                        heatStackModel.setEnvironment(lbEnv);
                    }
                    @SuppressWarnings("unchecked")
                    HashMap<String, String> parameters = (HashMap<String, String>) JSON.parseObject(templateParam,
                            Map.class);
                    parameters.put("max_size", autoScaling.getMaxSize() + "");
                    parameters.put("min_size", autoScaling.getMinSize() + "");
                    parameters.put("cooldown", autoScaling.getCooldown() + "");
                    heatStackModel.setParameters(parameters);
                    String projectName = null;
                    OSTenant osTenant = osTenantRepository.getByTenantUuid(cloudStack.getTenantUuid(),
                            vendor.getId());
                    if (null != osTenant) {
                        projectName = osTenant.getName();
                    }
                    bocloudResult = heatDriver.modifyStack(heatStackModel, projectName, vendor.getUuid(), null);
                    if (bocloudResult.isSuccess()) {
                        HeatStackModel stackModel = (HeatStackModel) bocloudResult.getData();
                        BeanUtils.copyProperties(stackModel, cloudStack);
                        cloudStack.setTemplateParam(JSON.toJSONString(parameters));
                        cloudStackRepository.update(cloudStack);
                        cloudStackService.syncStackEvent(stackModel, vendor.getId(), cloudStack.getId());
                        oldAutoScaling.setMaxSize(autoScaling.getMaxSize());
                        oldAutoScaling.setMinSize(autoScaling.getMinSize());
                        oldAutoScaling.setCooldown(autoScaling.getCooldown());
                        oldAutoScaling.setResources(syncResource(cloudStack));
                        oldAutoScaling.setTemplate(cloudStack.getTemplate());
                        oldAutoScaling.setStatus(cloudStack.getStatus());
                        autoScalingRepository.update(oldAutoScaling);
                        // 同步虚机
                        List<CloudServer> cloudservers = cloudServerRepository.queryByEnv(cloudStack.getId(),
                                vendor.getId());
                        if (null != cloudservers && !cloudservers.isEmpty()) {
                            for (CloudServer server : cloudservers) {
                                cloudServerRepository.remove(server.getId(), requestContext.getTarget());
                            }
                        }
                        syncResources(cloudStack, vendor, requestContext);
                        if (oldAutoScaling.getUseLb()) {
                            syncLoadBalancer(cloudStack, vendor, requestContext, oldAutoScaling);
                        }
                        content = "伸缩组编辑成功！";
                    } else {
                        content = bocloudResult.getMessage();
                    }
                } catch (Exception e) {
                    logger.error("伸缩组编辑失败：" + e.getMessage());
                    content = "伸缩组编辑失败：" + e.getMessage();
                } finally {
                    if (null != lock) {
                        try {
                            lock.close();
                        } catch (Exception e) {
                        }
                    }
                }
                resourceEventPublisher.send(new OperateResult(bocloudResult.isSuccess(), content, operate,
                        MapTools.simpleMap("vendorId", vendor.getId()), OperateResult.OperateCategory.ResourceEvent,
                        requestContext));

            }).start();
            return new BocloudResult<>(true, "编辑任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("modify fail:", e);
            return new BocloudResult<>(false, "伸缩组编辑失败", null, null);
        }
    }

    @Override
    public BocloudResult removeAutoScaling(Long id, RequestContext requestContext) {
        String path = AutoScaling.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            AutoScaling autoScaling = autoScalingRepository.query(id);
            Assert.notNull(autoScaling, "数据不存在!");
            CloudVendor vendor = cloudVendorRepository.query(autoScaling.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            CloudStack cloudStack = cloudStackRepository.query(autoScaling.getStackId());
            if (null == cloudStack) {
                autoScalingRepository.remove(id, requestContext.getTarget());
                return new BocloudResult<>(true, "删除成功！");
            }
            return cloudStackService.remove(cloudStack.getId(), requestContext);
        } catch (Exception e) {
            logger.error("remove fail:", e);
            return new BocloudResult<>(false, "删除失败", null, null);
        }
    }

    @Override
    public BocloudResult<AutoScalingConfig> createAutoScalingConfig(AutoScalingModel autoScalingModel, RequestContext requestContext) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(autoScalingModel.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            Image image = imageRepository.query(autoScalingModel.getImageId());
            Assert.notNull(image, "镜像不存在！");
            Flavor flavor = flavorRepository.query(autoScalingModel.getFlavorId());
            Assert.notNull(flavor, "规格不存在！");
            Keypair keypair = keypairRepository.query(autoScalingModel.getKeypairId());
            Assert.notNull(keypair, "秘钥数据不存在！");
            AutoScalingConfig autoScalingConfig = new AutoScalingConfig();
            BeanUtils.copyProperties(autoScalingModel, autoScalingConfig);
            autoScalingConfig.setCreatorId(requestContext.getTarget());
            autoScalingConfig.setMenderId(requestContext.getTarget());
            autoScalingConfig.setRegionId(autoScalingModel.getRegion());
            autoScalingConfig.setFlavorUuid(flavor.getFlavorUuid());
            autoScalingConfig.setImageUuid(image.getImageUuid());
            autoScalingConfig.setKeypairId(keypair.getId());
            autoScalingConfigRepository.save(autoScalingConfig);
            return new BocloudResult<>(true, autoScalingConfig, "创建成功");
        } catch (Exception e) {
            logger.error("Get error message:", e);
            return new BocloudResult<>(false, "创建失败");
        }
    }

    @Override
    public BocloudResult removeAutoScalingConfig(Long id, RequestContext requestContext) {
        String path = AutoScalingConfig.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            AutoScalingConfig autoScalingConfig = autoScalingConfigRepository.query(id);
            Assert.notNull(autoScalingConfig, "数据不存在!");
            CloudVendor cloudVendor = cloudVendorRepository.query(autoScalingConfig.getVendorId());
            Assert.notNull(cloudVendor, "平台验证失败");
            List<AutoScaling> autoScalings = autoScalingRepository.listByConfigId(id, cloudVendor.getId());
            Assert.isTrue(null == autoScalings || autoScalings.size() == 0, "伸缩配置正在使用中，不允许删除！");
            autoScalingConfigRepository.remove(id, requestContext.getTarget());
            return new BocloudResult<>(true, "删除成功");
        } catch (Exception e) {
            logger.error("remove fail:", e);
            return new BocloudResult<>(false, "删除失败", null, null);
        }
    }

    @Override
    public BocloudResult createAlarmTask(AutoScalingModel autoScalingModel, RequestContext requestContext) {
        try {
            AutoScaling autoScaling = autoScalingRepository.query(autoScalingModel.getAutoScalingId());
            Assert.notNull(autoScaling, "伸缩组不存在！");
            CloudVendor vendor = cloudVendorRepository.query(autoScalingModel.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            CloudStack cloudStack = cloudStackRepository.query(autoScaling.getStackId());
            Assert.notNull(cloudStack, "栈信息不存在！");
            String alarmAutoScalingType = autoScalingModel.getAlarmAutoScalingType();
            Assert.notNull(alarmAutoScalingType, "伸缩活动未知");
            String taskName = "";
            String adjustment = "";
            if ("add".equalsIgnoreCase(alarmAutoScalingType)) {
                taskName = "ALARM_ADD_" + System.currentTimeMillis();
                adjustment = autoScalingModel.getScalingAdjustment() + "";
            } else {
                taskName = "ALARM_DEL_" + System.currentTimeMillis();
                adjustment = (autoScalingModel.getScalingAdjustment() * -1) + "";
            }
            // 保存伸缩组告警数据
            String policyName = "POLICY_" + System.currentTimeMillis();
            AutoScalingAlarmTask autoScalingAlarmTask = new AutoScalingAlarmTask();
            BeanUtils.copyProperties(autoScalingModel, autoScalingAlarmTask);
            autoScalingAlarmTask.setCreatorId(requestContext.getTarget());
            autoScalingAlarmTask.setName(taskName);
            autoScalingAlarmTask.setAlarmPolicy(policyName);
            autoScalingAlarmTask.setVendorId(vendor.getId());
            autoScalingAlarmTask.setMenderId(requestContext.getTarget());
            autoScalingAlarmTask.setAutoScalingId(autoScaling.getId());
            autoScalingAlarmTask.setStatus(BocloudStatus.Server.BUILDING.name());
            autoScalingAlarmTaskRepository.save(autoScalingAlarmTask);
            final String scalingAdjustment = adjustment;
            final String alarmTaskName = taskName;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String path = AutoScaling.class.getSimpleName() + "_" + autoScalingModel.getAutoScalingId();
                    String operate = vendor.getType().toLowerCase() + ".alarmTask";
                    String content = "添加报警失败!";
                    BocloudResult bocloudResult = new BocloudResult<>(false, content);
                    BocloudACLock lock = null;
                    try {
                        lock = lockFactory.getACLock(path);
                        if (!lock.acquire(1, TimeUnit.MICROSECONDS)) {
                            logger.warn("Get harmonyLock time out!");
                            resourceEventPublisher.send(new OperateResult(false, "当前资源存在任务...请稍后再试！", operate,
                                    MapTools.simpleMap("vendorId", vendor.getId()),
                                    OperateResult.OperateCategory.ResourceEvent, requestContext));
                            autoScalingAlarmTaskRepository.remove(autoScalingAlarmTask.getId(),
                                    requestContext.getTarget());
                            return;
                        }
                        // 获取伸缩组原始template
                        String template = cloudStack.getTemplate();
                        Yaml yaml = new Yaml();
                        JSONObject object = JSON.parseObject(JSON.toJSONString(yaml.load(template)));
                        JSONObject resources = object.getJSONObject("resources");
                        // 获取 alarm template
                        String scalingPolicy = YamlUtil.readToString(StackConstants.SCALINGPOLICY_TEMPLATE);
                        scalingPolicy = scalingPolicy.replaceAll(StackConstants.POLICY_SCALING_ADJUSTMENT,
                                scalingAdjustment);
                        JSONObject cpuScalingPolicyObject = JSON
                                .parseObject(JSON.toJSONString(yaml.load(scalingPolicy)));
                        resources.put(policyName, cpuScalingPolicyObject);
                        resources.put(alarmTaskName, alarmTemplates(autoScalingModel, alarmTaskName, policyName));
                        object.put("resources", resources);
                        // template outputs
                        outputsTemplates(policyName, object);
                        HeatStackModel heatStackModel = new HeatStackModel();
                        if (autoScaling.getUseLb() == null ? false : autoScaling.getUseLb()) {
                            String lbEnv = YamlUtil.readToString(StackConstants.LB_ENV_FILENAME);
                            heatStackModel.setEnvironment(lbEnv);
                        }
                        heatStackModel.setName(cloudStack.getName());
                        heatStackModel.setTemplate(object.toJSONString());
                        heatStackModel.setStackUuid(cloudStack.getStackUuid());
                        String templateParam = cloudStack.getTemplateParam();
                        @SuppressWarnings("unchecked")
                        HashMap<String, String> parameters = (HashMap<String, String>) JSON.parseObject(templateParam,
                                Map.class);
                        if (null == parameters) {
                            parameters = new HashMap<>();
                        }
                        heatStackModel.setParameters(parameters);
                        String projectName = null;
                        OSTenant osTenant = osTenantRepository.getByTenantUuid(cloudStack.getTenantUuid(),
                                vendor.getId());
                        if (null != osTenant) {
                            projectName = osTenant.getName();
                        }
                        bocloudResult = heatDriver.modifyStack(heatStackModel, projectName, vendor.getUuid(), null);
                        if (bocloudResult.isSuccess()) {
                            HeatStackModel stackModel = (HeatStackModel) bocloudResult.getData();
                            BeanUtils.copyProperties(stackModel, cloudStack);
                            cloudStack.setTemplateParam(JSON.toJSONString(parameters));
                            cloudStackRepository.update(cloudStack);
                            // 告警创建成功状态
                            String alarmStatus = "CREATE_COMPLETE";
                            if (cloudStack.getStatus().contains("FAILED")) {
                                alarmStatus = "CREATE_FAILED";
                            }
                            autoScalingAlarmTask.setStatus(alarmStatus);
                            autoScalingAlarmTaskRepository.update(autoScalingAlarmTask);
                            autoScaling.setResources(syncResource(cloudStack));
                            autoScaling.setTemplate(cloudStack.getTemplate());
                            autoScaling.setStatus(cloudStack.getStatus());
                            autoScalingRepository.update(autoScaling);
                            cloudStackService.syncStackEvent(stackModel, vendor.getId(), cloudStack.getId());
                            content = "添加报警成功！";
                        } else {
                            autoScalingAlarmTaskRepository.remove(autoScalingAlarmTask.getId(),
                                    requestContext.getTarget());
                            content = bocloudResult.getMessage();
                        }
                    } catch (Exception e) {
                        logger.error("添加报警失败：" + e.getMessage());
                        try {
                            autoScalingAlarmTaskRepository.remove(autoScalingAlarmTask.getId(),
                                    requestContext.getTarget());
                        } catch (Exception e1) {
                            logger.error("删除告警策略异常：" + e.getMessage());
                        }
                        content = "添加报警失败：" + e.getMessage();
                    } finally {
                        if (null != lock) {
                            try {
                                lock.close();
                            } catch (Exception e) {
                            }
                        }
                    }
                    resourceEventPublisher.send(new OperateResult(bocloudResult.isSuccess(), content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), OperateResult.OperateCategory.ResourceEvent,
                            requestContext));

                }
            }).start();
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("Get error message:", e);
            return new BocloudResult<>(false, "创建失败");
        }
    }

    protected JSONObject alarmTemplates(AutoScalingModel autoScalingModel, String alarmTaskName, String policyName)
            throws Exception {
        Yaml yaml = new Yaml();
        String comparisonOperator = autoScalingModel.getComparisonOperator();
        String high = YamlUtil.readToString(StackConstants.ALARM_TEMPLATE_FILENAME);
        if (null == high) {
            throw new RuntimeException("获取告警模板异常！");
        }
        // 由于可以创建多条告警 所以stack 的 parameter无法满足
        high = high.replaceAll(StackConstants.ALARM_POLICY_NAME, policyName)
                .replaceAll(StackConstants.ALARM_DESCRIPTION,
                        "if cpu " + comparisonOperator + " " + autoScalingModel.getComparisonOperatorValue() + "%")
                .replaceAll(StackConstants.HIGH_PERIOD, autoScalingModel.getGranularity() + "")
                // 统计周期
                .replaceAll(StackConstants.HIGH_EVALUATION_PERIOED, autoScalingModel.getEvaluationPeriods() + "")
                .replaceAll(StackConstants.HIGH_THRESHOLD, autoScalingModel.getComparisonOperatorValue())
                .replaceAll(StackConstants.HIGH_COMPARISON_OPERATOR, comparisonOperator);
        return JSON.parseObject(JSON.toJSONString(yaml.load(high)));
    }

    protected void outputsTemplates(String policyName, JSONObject object) throws Exception {
        Yaml yaml = new Yaml();
        String outputs = YamlUtil.readToString(StackConstants.OUTPUTS_FILENAME);
        if (null == outputs) {
            throw new RuntimeException("获取模板Outputs异常！");
        }
        outputs = outputs.replaceAll(StackConstants.OUTPUTS_ALARM_POLICY_NAME, policyName);
        Object outputsResult = yaml.load(outputs);
        JSONObject outputsResultObj = JSON.parseObject(JSON.toJSONString(outputsResult));
        JSONObject outputsObjectResult = object.getJSONObject("outputs");
        if (null == outputsObjectResult) {
            outputsObjectResult = new JSONObject();
        }
        outputsObjectResult.put(policyName + "_URL", outputsResultObj);
        object.put("outputs", outputsObjectResult);
    }

    @Override
    public BocloudResult removeAlarmTask(Long id, RequestContext requestContext) {
        try {
            AutoScalingAlarmTask autoScalingAlarmTask = autoScalingAlarmTaskRepository.query(id);
            Assert.notNull(autoScalingAlarmTask, "数据不存在！");
            CloudVendor vendor = cloudVendorRepository.query(autoScalingAlarmTask.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            AutoScaling autoScaling = autoScalingRepository.query(autoScalingAlarmTask.getAutoScalingId());
            Assert.notNull(autoScaling, "伸缩组不存在！");
            CloudStack cloudStack = cloudStackRepository.query(autoScaling.getStackId());
            Assert.notNull(cloudStack, "栈信息不存在！");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String operate = vendor.getType().toLowerCase() + ".alarmTask";
                    String content = "删除报警失败!";
                    String path = AutoScaling.class.getSimpleName() + "_" + autoScaling.getId();
                    BocloudResult bocloudResult = new BocloudResult<>(false, content);
                    BocloudACLock lock = null;
                    try {
                        lock = lockFactory.getACLock(path);
                        if (!lock.acquire(1, TimeUnit.MICROSECONDS)) {
                            logger.warn("Get harmonyLock time out!");
                            resourceEventPublisher.send(new OperateResult(false, "当前资源存在任务...请稍后再试！", operate,
                                    MapTools.simpleMap("vendorId", vendor.getId()),
                                    OperateResult.OperateCategory.ResourceEvent, requestContext));

                            return;
                        }
                        String alarmName = autoScalingAlarmTask.getName();
                        String template = cloudStack.getTemplate();
                        Yaml yaml = new Yaml();
                        Object result = yaml.load(template);
                        JSONObject object = JSON.parseObject(JSON.toJSONString(result));
                        JSONObject resources = object.getJSONObject("resources");
                        resources.remove(alarmName);
                        resources.remove(autoScalingAlarmTask.getAlarmPolicy());
                        JSONObject outputs = object.getJSONObject("outputs");
                        outputs.remove(autoScalingAlarmTask.getAlarmPolicy() + "_URL");
                        if (outputs.keySet().size() == 0) {
                            object.remove("outputs");
                        } else {
                            object.put("outputs", outputs);
                        }
                        object.put("resources", resources);
                        HeatStackModel heatStackModel = new HeatStackModel();
                        if (autoScaling.getUseLb() == null ? false : autoScaling.getUseLb()) {
                            String lbEnv = YamlUtil.readToString(StackConstants.LB_ENV_FILENAME);
                            heatStackModel.setEnvironment(lbEnv);
                        }
                        heatStackModel.setName(cloudStack.getName());
                        heatStackModel.setTemplate(object.toJSONString());
                        heatStackModel.setStackUuid(cloudStack.getStackUuid());
                        String templateParam = cloudStack.getTemplateParam();
                        @SuppressWarnings("unchecked")
                        HashMap<String, String> parameters = (HashMap<String, String>) JSON.parseObject(templateParam,
                                Map.class);
                        heatStackModel.setParameters(parameters);
                        String projectName = null;
                        OSTenant osTenant = osTenantRepository.getByTenantUuid(cloudStack.getTenantUuid(),
                                vendor.getId());
                        if (null != osTenant) {
                            projectName = osTenant.getName();
                        }
                        bocloudResult = heatDriver.modifyStack(heatStackModel, projectName, vendor.getUuid(), null);
                        if (bocloudResult.isSuccess()) {
                            HeatStackModel stackModel = (HeatStackModel) bocloudResult.getData();
                            BeanUtils.copyProperties(stackModel, cloudStack);
                            cloudStack.setTemplateParam(JSON.toJSONString(parameters));
                            cloudStackRepository.update(cloudStack);
                            autoScaling.setResources(syncResource(cloudStack));
                            autoScaling.setTemplate(cloudStack.getTemplate());
                            autoScaling.setStatus(cloudStack.getStatus());
                            autoScalingRepository.update(autoScaling);
                            autoScalingAlarmTaskRepository.remove(id, requestContext.getTarget());
                            cloudStackService.syncStackEvent(stackModel, vendor.getId(), cloudStack.getId());
                            content = "删除报警成功！";
                        } else {
                            content = bocloudResult.getMessage();
                        }
                    } catch (Exception e) {
                        logger.error("删除报警失败：" + e.getMessage());
                        content = "删除报警失败：" + e.getMessage();
                    } finally {
                        if (null != lock) {
                            try {
                                lock.close();
                            } catch (Exception e) {
                            }
                        }
                    }
                    resourceEventPublisher.send(new OperateResult(bocloudResult.isSuccess(), content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), OperateResult.OperateCategory.ResourceEvent,
                            requestContext));
                }
            }).start();
            return new BocloudResult<>(true, "删除报警任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("remove fail:", e);
            return new BocloudResult<>(false, "删除失败", null, null);
        }
    }

    @Override
    public BocloudResult<AutoScalingTimedTask> createTimedTask(AutoScalingModel autoScalingModel, RequestContext requestContext) {
        try {
            AutoScaling autoScaling = autoScalingRepository.query(autoScalingModel.getAutoScalingId());
            Assert.notNull(autoScaling, "伸缩组不存在！");
            CloudVendor vendor = cloudVendorRepository.query(autoScalingModel.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            AutoScalingTimedTask autoScalingTimedTask = new AutoScalingTimedTask();
            BeanUtils.copyProperties(autoScalingModel, autoScalingTimedTask);
            autoScalingTimedTask.setCreatorId(requestContext.getTarget());
            autoScalingTimedTask.setMenderId(requestContext.getTarget());
            autoScalingTimedTaskRepository.save(autoScalingTimedTask);
            return new BocloudResult<>(true, autoScalingTimedTask, "创建成功");
        } catch (Exception e) {
            logger.error("Get error message:", e);
            return new BocloudResult<>(false, "创建失败");
        }
    }

    @Override
    public BocloudResult removeTimedTask(Long id, RequestContext requestContext) {
        String path = AutoScalingTimedTask.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            AutoScalingTimedTask autoScalingTimedTask = autoScalingTimedTaskRepository.query(id);
            Assert.notNull(autoScalingTimedTask, "数据不存在!");
            CloudVendor cloudVendor = cloudVendorRepository.query(autoScalingTimedTask.getVendorId());
            Assert.notNull(cloudVendor, "平台验证失败");
            autoScalingTimedTaskRepository.remove(id, requestContext.getTarget());
            return new BocloudResult<>(true, "删除成功");
        } catch (Exception e) {
            logger.error("remove fail:", e);
            return new BocloudResult<>(false, "删除失败", null, null);
        }
    }

    @Override
    public BocloudResult<AutoScaling> detail(Long id) {
        try {
            AutoScaling autoScaling = autoScalingRepository.query(id);
            Assert.notNull(autoScaling, "数据不存在!");
            return new BocloudResult<>(true, autoScaling, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }


    @Override
    public BocloudResult syncStackInfo(Long id, RequestContext requestContext) {
        String path = AutoScalingTimedTask.class.getSimpleName() + "_" + id;
        try {
            AutoScaling autoScaling = autoScalingRepository.query(id);
            Assert.notNull(autoScaling, "伸缩组信息异常！");
            CloudVendor vendor = cloudVendorRepository.query(autoScaling.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            CloudStack cloudStack = cloudStackRepository.query(autoScaling.getStackId());
            Assert.notNull(cloudStack, "栈信息异常！");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String operate = vendor.getType().toLowerCase() + ".alarmTask";
                    String content = "栈资源同步异常!";
                    BocloudResult bocloudResult = new BocloudResult<>(false, content);
                    BocloudACLock lock = null;
                    try {
                        lock = lockFactory.getACLock(path);
                        if (!lock.acquire(1, TimeUnit.MICROSECONDS)) {
                            logger.warn("Get harmonyLock time out!");
                            resourceEventPublisher.send(new OperateResult(false, "当前资源存在任务...请稍后再试！", operate,
                                    MapTools.simpleMap("vendorId", vendor.getId()),
                                    OperateResult.OperateCategory.ResourceEvent, requestContext));
                            return;
                        }
                        String projectName = null;
                        OSTenant osTenant = osTenantRepository.getByTenantUuid(cloudStack.getTenantUuid(),
                                vendor.getId());
                        if (null != osTenant) {
                            projectName = osTenant.getName();
                        }
                        HeatStackModel heatStackModel = new HeatStackModel();
                        heatStackModel.setName(cloudStack.getName());
                        heatStackModel.setStackUuid(cloudStack.getStackUuid());
                        bocloudResult = heatDriver.detailStack(heatStackModel, projectName, vendor.getUuid(), null);
                        if (bocloudResult.isSuccess()) {
                            heatStackModel = (HeatStackModel) bocloudResult.getData();
                            BeanUtils.copyProperties(heatStackModel, cloudStack);
                            cloudStackRepository.update(cloudStack);
                            syncResources(cloudStack, vendor, requestContext);
                            if (autoScaling.getUseLb() == null ? false : autoScaling.getUseLb()) {
                                syncLoadBalancer(cloudStack, vendor, requestContext, autoScaling);
                            }
                            content = "栈资源同步成功！";
                        } else {
                            content = bocloudResult.getMessage();
                        }
                    } catch (Exception e) {
                        logger.error("栈资源同步失败：" + e.getMessage());
                        content = "栈资源同步失败：" + e.getMessage();
                    } finally {
                        if (null != lock) {
                            try {
                                lock.close();
                            } catch (Exception e) {
                            }
                        }
                    }
                    resourceEventPublisher.send(new OperateResult(bocloudResult.isSuccess(), content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), OperateResult.OperateCategory.ResourceEvent,
                            requestContext));
                }
            }).start();
            return new BocloudResult<>(true, "同步任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("sync fail:", e);
            return new BocloudResult<>(false, "同步失败", null, null);
        }
    }

    class StackConstants {
        static final String GROUP_TEMPLATE_FILENAME = "group_template.yaml";
        static final String LB_GROUP_TEMPLATE_FILENAME = "lb_group_template.yaml";
        static final String LB_ENV_FILENAME = "lb_env.yaml";
        static final String ALARM_TEMPLATE_FILENAME = "alarm_template.yaml";
        static final String OUTPUTS_FILENAME = "outputs.yaml";
        static final String SCALINGPOLICY_TEMPLATE = "scalingPolicy_template.yaml";

        static final String POLICY_SCALING_ADJUSTMENT = "policy_scaling_adjustment";
        static final String HIGH_COMPARISON_OPERATOR = "high_comparison_operator";
        static final String HIGH_THRESHOLD = "high_threshold";
        static final String HIGH_EVALUATION_PERIOED = "high_evaluation_periods";
        static final String HIGH_PERIOD = "high_period";
        static final String ALARM_DESCRIPTION = "alarm_description";
        static final String ALARM_POLICY_NAME = "alarm_policy_name";
        static final String OUTPUTS_ALARM_POLICY_NAME = "outputs_alarm_policy_name";

        static final String SERVER_RESOURCE_TYPE = "OS::Nova::Server";
    }
}
