package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.common.FlavorDriver;
import com.bocloud.cmp.driver.compute.ImageDriver;
import com.bocloud.cmp.driver.compute.ServerDriver;
import com.bocloud.cmp.driver.monitor.MonitorDriver;
import com.bocloud.cmp.driver.storage.VolumeDriver;
import com.bocloud.cmp.entity.enums.*;
import com.bocloud.cmp.model.*;
import com.bocloud.cmp.model.common.ElementModel;
import com.bocloud.cmp.model.common.OrderItem;
import com.bocloud.cmp.model.common.SpecModel;
import com.bocloud.cmp.provider.utils.IPAddress;
import com.bocloud.cmp.vm.model.*;
import com.bocloud.common.encrypt.AESEncrptor;
import com.bocloud.common.encrypt.DESEncrptor;
import com.bocloud.common.encrypt.Encryptor;
import com.bocloud.common.enums.BoCloudService;
import com.bocloud.common.enums.ResourceCatalog;
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.Project;
import com.bocloud.ims.entity.params.ServerPerformanceParam;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.Ip.IpStatus;
import com.bocloud.ims.entity.resource.manageone.ManageOneAccount;
import com.bocloud.ims.interfaces.manageone.ManageOneAccountService;
import com.bocloud.ims.interfaces.resource.*;
import com.bocloud.ims.interfaces.scheduler.SnapshotTaskService;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.service.internal.CosInternalService;
import com.bocloud.ims.service.internal.SmsProjectService;
import com.bocloud.ims.service.internal.worker.LvmService;
import com.bocloud.ims.service.internal.worker.VmToolsInstallService;
import com.bocloud.ims.service.model.ResultTrend;
import com.bocloud.ims.service.model.TrendData;
import com.bocloud.ims.service.model.cmdb.CmdbInfo;
import com.bocloud.ims.service.transportor.OpenstackTransportor;
import com.bocloud.ims.service.transportor.PowervcTransportor;
import com.bocloud.ims.service.utils.*;
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.apache.commons.lang3.time.DateUtils;
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.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 虚拟机扩展实现类
 *
 * @author weiwei
 */
@Service("vmExtendService")
public class VMExtendServiceImpl implements VMExtendService {

    private static Logger logger = LoggerFactory.getLogger(VMExtendServiceImpl.class);
    private static OperateCategory operateCategory = OperateResult.OperateCategory.ResourceEvent;
    @Autowired
    private SubnetRepository subnetRepository;
    @Autowired
    private VolumeDriver volumeDriver;
    @Autowired
    private SmsProjectService smsProjectService;
    @Autowired
    private FlavorRepository flavorRepository;
    @Autowired
    private FlavorExtraSpecsRepository flavorExtraSpecsRepository;
    @Autowired
    private PortRepository portRepository;
    @Autowired
    private FloatingIpRepository floatingIpRepository;
    @Autowired
    private SecurityGroupRepository securityGroupRepository;
    @Autowired
    private ServerSgroupRepository serverSgroupRepository;
    @Autowired
    private FlavorDriver flavorDriver;
    @Autowired
    private PortFixedIpRepository portFixedIpRepository;
    @Autowired
    private RegionRepository regionRepository;
    @Autowired
    private KeypairRepository keyPairRepository;
    @Autowired
    private ServerKeypairRepository serverKeyPairRepository;
    @Autowired
    private PortService portService;
    @Autowired
    private QosPolicyRepository qosPolicyRepository;
    @Autowired
    private VendorProjectService vendorProjectService;
    @Autowired
    private OSTenantRepository osTenantRepository;
    @Autowired
    private CloudServerRepository cloudServerRepository;
    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private ResourceEventRepository resourceEventRepository;
    @Autowired
    private ImageRepository imageRepository;
    @Autowired
    private DataStoreRepository dataStoreRepository;
    @Autowired
    private PowervcTransportor powervcTransportor;
    @Autowired
    private ServerRepository serverRepository;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private ServerDriver serverDriver;
    @Autowired
    private StoreHostRepository storeHostRepository;
    @Autowired
    private NetworkRepository networkRepository;
    @Autowired
    private PortGroupRepository portGroupRepository;
    @Autowired
    private SwitcherRepository switcherRepository;
    @Autowired
    private NetworkHostRepository networkHostRepository;
    @Autowired
    private MonitorDriver monitorDriver;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private ResourceRepository resourceRepository;
    @Autowired
    private IpRepository ipRepository;
    @Autowired
    private IpPoolRepository ipPoolRepository;
    @Autowired
    private ObjectRelationRepository objectRelationRepository;
    @Autowired
    private VolumeRepository volumeRepository;
    @Autowired
    private VdcRepository vdcRepository;
    @Autowired
    private ClusterRepository clusterRepository;
    @Autowired
    private CmdbMessagePublisher cmdbMessagePublisher;
    @Autowired
    private ServerOperationHelper serverOperationHelper;
    @Autowired
    private ServerConfigRepository serverConfigRepository;
    @Autowired
    private VmToolsInstallService vmToolsInstallService;
    @Autowired
    private PoolGroupRelationRepository poolGroupRelationRepository;
    @Autowired
    private PoolGroupRepository poolGroupRepository;
    @Autowired
    private CloudServerService cloudServerService;
    @Autowired
    private VMApplyService vmApplyService;
    @Autowired
    private RouterRepository routerRepository;
    @Autowired
    private ManageOneAccountService accountService;
    @Value("${manageone.vnc.console.url:172.23.53.21}")
    private String manageOneVncConsoleUrl;
    @Autowired
    private LvmService lvmService;
    @Autowired
    private SnapshotRepository snapshotRepository;
    @Autowired
    private NetworkCardRepository networkCardRepository;
    @Autowired
    private LabelRepository labelRepository;
    @Autowired
    private LabelService labelService;
    @Autowired
    private ServerLabelRepository serverLabelRepository;
    @Autowired
    private ImageDriver imageDriver;
    @Autowired
    private CosInternalService cosInternalService;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private SnapshotTaskService snapshotTaskService;

    private static final SimpleDateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public BocloudResult stats(String range, Long hostId, RequestContext context) {
        try {
            ResultTrend trend = new ResultTrend();
            List<String> keys = Lists.newArrayList();
            StatsRange statsRange = StatsRange.valueOf(range);
            Date beginDate = null;
            Date endDate = DateUtils.addDays(new Date(), 1);
            switch (statsRange) {
                case WEEK:
                    beginDate = DateUtils.addWeeks(endDate, -1);
                    break;
                case MONTH:
                    beginDate = DateUtils.addMonths(endDate, -1);
                    break;
                case QUARTER:
                    beginDate = DateUtils.addMonths(endDate, -3);
                    break;
                case HALFYEAR:
                    beginDate = DateUtils.addMonths(endDate, -6);
                    break;
                case YEAR:
                    beginDate = DateUtils.addYears(endDate, -1);
                    break;
                default:
                    beginDate = DateUtils.addWeeks(endDate, -1);
                    break;
            }
            hostId = Optional.ofNullable(hostId).orElseThrow(() -> new Exception("计算节点不存在"));
            List<CloudServer> vms = cloudServerRepository.summary(beginDate, endDate, hostId);
            List<TrendData> values = new ArrayList<>();
            List<String> cpuList = new ArrayList<>();
            List<String> memoryList = new ArrayList<>();
            List<String> vmList = new ArrayList<>();
            while (beginDate.before(endDate)) {
                String key = FORMAT.format(beginDate);
                keys.add(key);
                Date begin = DateUtils.parseDate(key + " 00:00:00", "yyyy-MM-dd HH:mm:ss");
                Date end = DateUtils.parseDate(key + " 23:59:59", "yyyy-MM-dd HH:mm:ss");
                Integer cpu = 0;
                Double memory = 0.0;
                Integer vmTotal = 0;
                for (CloudServer vm : vms) {
                    if (null != vm.getIsTemplate() && vm.getIsTemplate()) {
                        continue;
                    }
                    if (vm.getGmtCreate().after(begin) && vm.getGmtCreate().before(end)) {
                        cpu += null == vm.getCpu() ? 0 : vm.getCpu();
                        memory += null == vm.getMemory() ? 0.0 : vm.getMemory().doubleValue();
                        vmTotal++;
                    }
                }
                cpuList.add(String.valueOf(cpu));
                memoryList.add(String.valueOf(memory));
                vmList.add(String.valueOf(vmTotal));
                beginDate = DateUtils.addDays(beginDate, 1);
            }
            values.add(new TrendData("CPU(C)", cpuList));
            values.add(new TrendData("内存(GB)", memoryList));
            values.add(new TrendData("虚机(个)", vmList));
            trend = new ResultTrend(keys, values);
            return new BocloudResult<>(true, trend, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message:{}", e.getMessage());
            return new BocloudResult<>(false, e.getMessage());
        }
    }

    public enum StatsRange {
        WEEK, MONTH, QUARTER, HALFYEAR, YEAR
    }

    @Override
    public BocloudResult modifyAccount(Long id, String account, String password, RequestContext context) {
        try {
            CloudServer server = cloudServerRepository.query(id);
            server = Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            if (!StringUtils.isEmpty(account)) {
                server.setAccount(account);
            }
            Encryptor encrptor = new AESEncrptor();
            server.setPswd(encrptor.decrypt(password, null));
            cloudServerRepository.update(server);
            return new BocloudResult<>(true, "修改成功");
        } catch (Exception e) {
            logger.error("Update server account error:", e.getMessage());
            return new BocloudResult<>(false, e.getMessage());
        }
    }

    /**
     * 实时查看虚拟机详细信息
     *
     * @param id
     */
    @Override
    public BocloudResult<ServerModel> detailInRealTime(Long id) {
        try {
            CloudServer vm = cloudServerRepository.query(id);
            Optional.ofNullable(vm).orElseThrow(() -> new Exception("虚拟机不存在"));
            String instanceId = vm.getInstanceId();
            Long vendorId = vm.getVendorId();
            Optional.ofNullable(vendorId).orElseThrow(() -> new Exception("虚拟机信息的所属平台信息缺失"));
            CloudVendor vendor = this.cloudVendorRepository.query(vendorId);
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            String vendorUuid = vendor.getUuid();
            BocloudResult result = serverDriver.detail(instanceId, vendorUuid, null);
            if (result.isFailed()) {
                return new BocloudResult<>(false, result.getMessage());
            }
            Object data = result.getData();
            ServerModel model = null;
            if (data instanceof ServerModel) {
                model = (ServerModel)data;
            } else {
                model = JSON.parseObject(JSON.toJSONString(data), ServerModel.class);
            }
            return new BocloudResult<>(true, model, "查询成功");
        } catch (Exception e) {
            logger.error("实时查看虚拟机详细信息失败:", e);
            return new BocloudResult<>(false, "实时查看虚拟机详细信息失败");
        }
    }

    @Override
    public BocloudResult vncconsole(String params, RequestContext context) {
        // 获取所有的
        JSONObject object = JSONTools.isJSONObj(params);
        String vncType = object.getString("vncType");
        String serverId = object.getString("serverId");
        String region = object.getString(Common.REGION);
        try {
            CloudServer server = cloudServerRepository.getByInstanceId(serverId);
            Assert.notNull(server, "云主机不存在");
            CloudVendor vendor = this.cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            BocloudResult result = null;
            if (CloudProvider.MANAGEONE.name().equals(vendor.getType()) && null != context.getTenant()
                && 0L != context.getTenant()) {
                ManageOneAccount account = accountService.queryAccount(vendor.getId(), context.getTenant());
                Assert.notNull(account, "认证失败！");
                result = serverDriver.vncConsole(serverId, vendor.getUuid(), account.getUsername(),
                    account.getPassword(), account.getProjectId(), account.getDomainName());
            } else {
                result = serverDriver.vncConsole(vncType, serverId, vendor.getUuid(), region);
            }
            if (CloudProvider.MANAGEONE.name().equals(vendor.getType())) {
                if (result.isSuccess()) {
                    String url = String.valueOf(result.getData());
                    String[] urlSplit = url.split(":");
                    String newUrl = urlSplit[0] + "://" + manageOneVncConsoleUrl + ":" + urlSplit[2];
                    result.setData(newUrl);
                }
            }
            return result.isSuccess() ? result : new BocloudResult<>(false, "vnc链接失败！");
        } catch (Exception e) {
            logger.error("查询数据失败：{}", e.getMessage());
            return new BocloudResult<>(false, e.getMessage());
        }
    }

    @Override
    public BocloudResult<List<PortGroup>> networks(Long hostId) {
        try {
            // 查询虚拟机端口组
            List<PortGroup> groups = Lists.newArrayList();
            List<Switcher> switchers = switcherRepository.listByHostId(hostId);
            for (Switcher switcher : switchers) {
                List<PortGroup> portGroups = portGroupRepository.listBySwitcher(switcher.getId());
                for (PortGroup portGroup : portGroups) {
                    if (portGroup.getType().equals(NetworkType.PortGroupType.VIRTUAL.name())) {
                        portGroup.setSwitchType(NetworkType.SwitchType.VSWITCH.name());
                        groups.add(portGroup);
                    }
                }
            }
            List<NetworkHost> hosts = networkHostRepository.listByVhostId(hostId, "PM");
            // 查询分布式端口组
            for (NetworkHost host : hosts) {
                Network network = networkRepository.query(host.getNetworkId());
                if (null != network && null != network.getSwitcherId() && 0L != network.getSwitcherId()) {
                    List<PortGroup> portGroups = portGroupRepository.listBySwitcher(network.getSwitcherId());
                    for (PortGroup portGroup : portGroups) {
                        if (portGroup.getType().equals(NetworkType.PortGroupType.DVPORT.name())) {
                            Switcher switcher = switcherRepository.query(portGroup.getSwitcherId());
                            portGroup.setName(portGroup.getName());
                            portGroup.setSwitchName(switcher.getName());
                            portGroup.setSwitchType(switcher.getType());
                            groups.add(portGroup);
                        }
                    }
                }
            }
            return new BocloudResult<>(true, groups, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult updateResourceGroup(String[] ids, String resourceGroup, Long id) {
        List<Resource> resources = new ArrayList<>();
        List<CloudServer> cloudServers = new ArrayList<>();
        try {
            for (String serverid : ids) {
                CloudServer cloudServer = cloudServerRepository.query(Long.valueOf(serverid));
                if (null != cloudServer) {
                    cloudServer.setResourceGroup(resourceGroup);
                    cloudServers.add(cloudServer);
                }
                Resource resource = resourceRepository.query(ResourceCategory.Computer.name(),
                    ResourceCatalog.LOGICAL.name(), Long.valueOf(serverid));
                if (null != resource) {
                    resource.setResourceGroup(resourceGroup);
                    resources.add(resource);
                }
            }
            for (CloudServer cloudServer : cloudServers) {
                cloudServerRepository.update(cloudServer);
            }
            for (Resource resource : resources) {
                resourceRepository.update(resource);
            }
        } catch (Exception e) {
            logger.error("查询资源异常", e);
            return new BocloudResult<>(false, "更新配置分组失败");
        }
        return new BocloudResult<>(true, "更新配置分组成功");
    }

    @Override
    public BocloudResult osChangePwd(Long vendorId, Long id, String password, RequestContext context) {
        String path = CloudServer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            // 云供应商
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Assert.notNull(vendor, "云平台不存在！");
            CloudServer server = cloudServerRepository.get(id);
            Assert.notNull(server, "虚拟机不存在！");
            CloudServer serverAccount = cloudServerRepository.queryAccount(id);
            server.setAccount(serverAccount.getAccount());
            Encryptor encryptor = new AESEncrptor();
            password = encryptor.decrypt(password, null);
            BocloudResult result =
                serverDriver.changePassword(server.getInstanceId(), vendor.getUuid(), server.getRegionId(), password);
            ResourceEvent event = new ResourceEvent(id, "修改密码", result.isSuccess() ? "成功" : "失败", context.getTarget(),
                new Date(), "VM", vendor.getId(), context.getCatalog());
            resourceEventRepository.save(event);
            if (result.isFailed()) {
                return new BocloudResult<>(false, result.getMessage());
            }
            server.setPswd(password);
            cloudServerRepository.update(server);
            return new BocloudResult<>(true, "密码修改成功");
        } catch (Exception e) {
            logger.error("change cloud server password fail:", e.getMessage());
            return new BocloudResult<>(false, "虚拟机密码修改失败");
        }
    }

    @Override
    public BocloudResult<CloudServer> queryAccount(Long serverId) {
        try {
            CloudServer server = cloudServerRepository.queryAccount(serverId);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            return new BocloudResult<>(true, server, "查询成功");
        } catch (Exception e) {
            logger.info("query server flavor error:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult attachNetwork(AttachNetworkParam params, RequestContext context) {
        // 虚拟机ID
        Long id = params.getId();
        Long policyId = params.getPolicyId();
        String path = CloudServer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            Long vendorId = server.getVendorId();
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            // 挂载网络
            if (ListTool.isEmpty(params.getNetworks())) {
                logger.error("Network information does not exist!");
                return new BocloudResult<>(false, "网络信息不存在!");
            }
            if (CloudProvider.MANAGEONE.name().equals(vendor.getType())) {
                return manageOneAttachNetwork(params, server, context);
            }
            List<NetworkBean> beans = params.getNetworks();
            NetworkBean networkBean = beans.get(0);
            Network network = networkRepository.query(networkBean.getNetworkId());
            Optional.ofNullable(network).orElseThrow(() -> new Exception("网络不存在"));
            if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
                // Powervc要求同一个网络不允许挂在给多个虚拟机
                List<Port> ports = portRepository.listByDeviceId(server.getInstanceId(), vendorId);
                for (Port port : ports) {
                    if (port.getNetworkId().equals(networkBean.getNetworkId())) {
                        return new BocloudResult<>(false, "该网络已经填加到虚拟机，不可重复添加!");
                    }
                }
                // 获取一下RMC状态，不活动的话就不允许附加网卡
                if (!BocloudStatus.Server.STOPPED.name().equals(server.getStatus())) {
                    BocloudResult result = serverDriver.detail(server.getInstanceId(), vendor.getUuid(), null);
                    if (result.isFailed()) {
                        return new BocloudResult<>(false, "获取虚拟机详情失败：" + result.getMessage());
                    }
                    ServerModel serverModel = (ServerModel)result.getData();
                    String rmcStatus = JSON.parseObject(serverModel.getProps()).getString("rmcStatus");
                    if (!"active".equals(rmcStatus)) {
                        return new BocloudResult<>(false, "该虚拟机不具备有效RMC连接，您可以关闭该虚拟机或将该虚拟机的RMC连接进入活动状态后再试！");
                    }
                }
            }
            networkBean.setNetworkUuid(network.getNetworkUuid());
            networkBean.setNetworkName(network.getName());
            List<AddressBean> addressBeans = networkBean.getAddresses();
            if (!ListTool.isEmpty(addressBeans)) {
                AddressBean address = addressBeans.get(0);
                if (address.getSubnetId() != null) {
                    Subnet subnet = subnetRepository.query(address.getSubnetId());
                    Optional.ofNullable(subnet).orElseThrow(() -> new Exception("网络下无可用子网"));
                    address.setSubnetUuid(subnet.getSubnetUuid());
                    address.setSubnetName(subnet.getName());
                    address.setNetworkId(network.getId());
                    String addr = address.getAddress();
                    if (!StringUtils.isEmpty(addr)) {
                        // 判断IP是否存在于指定网络的IP池中
                        Ip ip = ipRepository.checkExist(addr, address.getSubnetId(), vendor.getId());
                        if (null != ip) {
                            return new BocloudResult<>(false, "指定的IP地址【" + addr + "】已被使用");
                        }
                        networkBean.setFixIp(addr);
                    }
                }
            }
            QosPolicy qosPolicy = qosPolicyRepository.query(policyId);
            ServerModel serverModel = new ServerModel();
            serverModel.setInstanceId(server.getInstanceId());
            serverModel.setNetworkBeans(beans);
            if (null != qosPolicy) {
                serverModel.setPolicyUuid(qosPolicy.getPolicyUuid());
            }
            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".vm";
                OperateResult message = new OperateResult(false, "网卡挂载失败", operate,
                    MapTools.simpleMap(Common.VENDORID, vendorId), OperateCategory.ResourceEvent, context);
                try {
                    // 挂载网卡
                    OSTenant tenant = osTenantRepository.getByTenantUuid(server.getTenantUuid(), server.getVendorId());
                    String projectName = null;
                    if (null != tenant) {
                        projectName = tenant.getName();
                    }
                    BocloudResult bocloudResult =
                        serverDriver.attachNetwork(vendor.getUuid(), projectName, null, serverModel);
                    if (bocloudResult.isSuccess()) {
                        if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
                            ServerModel model = (ServerModel)bocloudResult.getData();
                            for (PortModel portModel : model.getPorts()) {
                                powervcTransportor.insertOrUpdate(vendor, portModel, context.getTarget());
                                if (portModel.getPortFixedIps().size() != 0) {
                                    for (PortFixedIpModel portFixedIp : portModel.getPortFixedIps()) {
                                        Subnet subnet = subnetRepository.getBySubId(portFixedIp.getSubnetUuid());
                                        if (subnet != null) {
                                            powervcTransportor.insertOrUpdate(subnet, portFixedIp.getIpAddress(),
                                                context.getTarget());
                                        }
                                    }
                                }
                            }
                            powervcTransportor.insertOrUpdate(vendor, model, context.getTarget());
                        } else {
                            ServerModel model =
                                serverOperationHelper.parseObject(bocloudResult.getData(), ServerModel.class);
                            List<PortModel> ports = model.getPorts();
                            // 保存端口信息
                            PortModel portModel = null;
                            if (CloudProvider.FUSIONCLOUD.name().equals(vendor.getType())
                                || CloudProvider.MANAGEONE.name().equals(vendor.getType())) {
                                List<Port> oldPorts =
                                    portRepository.listByDeviceId(server.getInstanceId(), server.getVendorId());
                                Map<String, Port> portMap = Maps.newHashMap();
                                for (Port oldPort : oldPorts) {
                                    portMap.put(oldPort.getPortUuid(), oldPort);
                                }
                                for (PortModel port : ports) {
                                    if (!portMap.containsKey(port.getPortUuid())) {
                                        portModel = port;
                                        break;
                                    }
                                }
                            } else {
                                portModel = ports.get(0);
                            }
                            Port port = new Port();
                            BeanUtils.copyProperties(portModel, port);
                            port.preSave(context.getTarget(), context.getTarget(), vendorId,
                                networkBean.getNetworkId());
                            port.setStatus(BocloudStatus.Network.RUNNING.name());
                            // 电科云 虚拟机IP绑定带宽 2019年11月11日17:36:12
                            if (null != qosPolicy) {
                                port.setQosPolicyUuid(qosPolicy.getPolicyUuid());
                                port.setMaxKbps(qosPolicy.getMaxKbps());
                            }
                            portRepository.save(port);
                            List<PortFixedIpModel> portFixedIps = portModel.getPortFixedIps();
                            List<PortFixedIpModel> fixedIps = new ArrayList<>();
                            PortFixedIpModel fixedIpModel = portFixedIps.get(0);
                            fixedIps.add(fixedIpModel);
                            Subnet subnet = subnetRepository.getBySubId(fixedIpModel.getSubnetUuid());
                            OpenstackTransportor toolOS = new OpenstackTransportor(ipRepository, ipPoolRepository,
                                subnetRepository, portFixedIpRepository);
                            toolOS.batchSavePortFixedIp(fixedIps, port.getPortUuid(), port.getId(), vendorId);
                            Ip ip = ipRepository.checkExist(fixedIpModel.getIpAddress(), subnet.getId(), vendorId);
                            if (null == ip) {
                                String mask =
                                    IPAddress.getIPAddress(fixedIpModel.getIpAddress()).getMask(subnet.getCidr());
                                ip = new Ip(fixedIpModel.getIpAddress(), mask, subnet.getGateway(),
                                    subnet.getDnsNames(), vendorId, 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(), vendorId);
                                if (null != pool) {
                                    ip.setPoolId(pool.getId());
                                }
                                ipRepository.save(ip);
                            }
                            server.setPrivateIps(serverOperationHelper.getPrivateIps(server, vendor));
                            cloudServerRepository.update(server);
                            // 同步资源表
                            serverOperationHelper.syncOsVResource(vendorId, server, context.getTarget());
                        }
                        message.setSuccess(true);
                        message.setMessage("网卡挂载成功");
                    } else {
                        message.setSuccess(false);
                        message.setMessage(bocloudResult.getMessage());
                    }
                    ResourceEvent event = new ResourceEvent(id, "网卡挂载", bocloudResult.isSuccess() ? "成功" : "失败",
                        context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                    resourceEventRepository.save(event);
                    resourceEventPublisher.send(message);
                } catch (Exception e) {
                    logger.error("attach port to cloud server fail:", e);
                    resourceEventPublisher.send(message);
                }
            }).start();
            return new BocloudResult<>(true, "挂载网卡任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("openstack CloudServer mount network fail:", e);
            return new BocloudResult<>(false, "网卡挂载失败：" + e.getMessage());
        }
    }

    private BocloudResult manageOneAttachNetwork(AttachNetworkParam params, CloudServer server,
        RequestContext context) {
        try {
            Long vendorId = server.getVendorId();
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            List<NetworkBean> beans = params.getNetworks();
            NetworkBean networkBean = beans.get(0);
            Router router = routerRepository.query(networkBean.getRouterId());
            Optional.ofNullable(router).orElseThrow(() -> new Exception("网络不存在"));
            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".vm";
                OperateResult message = new OperateResult(false, "网卡挂载失败", operate,
                    MapTools.simpleMap(Common.VENDORID, vendorId), OperateCategory.ResourceEvent, context);
                try {
                    ServerModel serverModel = new ServerModel();
                    serverModel.setInstanceId(server.getInstanceId());
                    List<AddressBean> addressBeans = networkBean.getAddresses();
                    if (!ListTool.isEmpty(addressBeans)) {
                        for (AddressBean address : addressBeans) {
                            if (address.getSubnetId() != null) {
                                Subnet subnet = subnetRepository.query(address.getSubnetId());
                                Optional.ofNullable(subnet).orElseThrow(() -> new Exception("网络下无可用子网"));
                                address.setSubnetUuid(subnet.getSubnetUuid());
                                address.setNetworkUuid(subnet.getNetworkUuid());
                                networkBean.setNetworkUuid(subnet.getNetworkUuid());
                                networkBean.setNetworkId(subnet.getNetworkId());
                                address.setSubnetName(subnet.getName());
                                String addr = address.getAddress();
                                if (!StringUtils.isEmpty(addr)) {
                                    // 判断IP是否存在于指定网络的IP池中
                                    Ip ip = ipRepository.checkExist(addr, address.getSubnetId(), vendor.getId());
                                    if (null != ip) {
                                        message.setMessage("指定的IP地址【" + addr + "】已被使用");
                                        resourceEventPublisher.send(message);
                                        continue;
                                    }
                                }
                                List<AddressBean> addresses = new ArrayList<>();
                                addresses.add(address);
                                networkBean.setAddresses(addresses);
                                List<NetworkBean> networkCards = new ArrayList<>();
                                networkCards.add(networkBean);
                                serverModel.setNetworkBeans(networkCards);
                                // 挂载网卡
                                OSTenant tenant =
                                    osTenantRepository.getByTenantUuid(server.getTenantUuid(), server.getVendorId());
                                String projectName = null;
                                if (null != tenant) {
                                    projectName = tenant.getName();
                                }
                                BocloudResult bocloudResult =
                                    serverDriver.attachNetwork(vendor.getUuid(), projectName, null, serverModel);
                                if (bocloudResult.isSuccess()) {
                                    ServerModel model =
                                        serverOperationHelper.parseObject(bocloudResult.getData(), ServerModel.class);
                                    List<PortModel> ports = model.getPorts();
                                    PortModel portModel = null;
                                    List<Port> oldPorts =
                                        portRepository.listByDeviceId(server.getInstanceId(), server.getVendorId());
                                    Map<String, Port> portMap = Maps.newHashMap();
                                    for (Port oldPort : oldPorts) {
                                        portMap.put(oldPort.getPortUuid(), oldPort);
                                    }
                                    for (PortModel port : ports) {
                                        if (!portMap.containsKey(port.getPortUuid())) {
                                            portModel = port;
                                            break;
                                        }
                                    }
                                    Port port = new Port();
                                    BeanUtils.copyProperties(portModel, port);
                                    port.preSave(context.getTarget(), context.getTarget(), vendorId,
                                        networkBean.getNetworkId());
                                    port.setStatus(BocloudStatus.Network.RUNNING.name());
                                    portRepository.save(port);
                                    List<PortFixedIpModel> portFixedIps = portModel.getPortFixedIps();
                                    List<PortFixedIpModel> fixedIps = new ArrayList<>();
                                    PortFixedIpModel fixedIpModel = portFixedIps.get(0);
                                    fixedIps.add(fixedIpModel);
                                    OpenstackTransportor toolOS = new OpenstackTransportor(ipRepository,
                                        ipPoolRepository, subnetRepository, portFixedIpRepository);
                                    toolOS.batchSavePortFixedIp(fixedIps, port.getPortUuid(), port.getId(), vendorId);
                                    Ip ip =
                                        ipRepository.checkExist(fixedIpModel.getIpAddress(), subnet.getId(), vendorId);
                                    if (null == ip) {
                                        String mask = IPAddress.getIPAddress(fixedIpModel.getIpAddress())
                                            .getMask(subnet.getCidr());
                                        ip = new Ip(fixedIpModel.getIpAddress(), mask, subnet.getGateway(),
                                            subnet.getDnsNames(), vendorId, 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(), vendorId);
                                        if (null != pool) {
                                            ip.setPoolId(pool.getId());
                                        }
                                        ipRepository.save(ip);
                                    }
                                    server.setPrivateIps(serverOperationHelper.getPrivateIps(server, vendor));
                                    server.setRouterUuid(subnet.getVpcUuid());
                                    cloudServerRepository.update(server);
                                    // 同步资源表
                                    serverOperationHelper.syncOsVResource(vendorId, server, context.getTarget());
                                    message.setSuccess(true);
                                    message.setMessage(
                                        "【" + server.getName() + "】网卡【" + fixedIpModel.getIpAddress() + "】挂载成功");
                                } else {
                                    message.setSuccess(false);
                                    message.setMessage(bocloudResult.getMessage());
                                }
                                ResourceEvent event =
                                    new ResourceEvent(server.getId(), "网卡挂载", bocloudResult.isSuccess() ? "成功" : "失败",
                                        context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                                resourceEventRepository.save(event);
                                resourceEventPublisher.send(message);

                            }
                        }
                    }

                } catch (Exception e) {
                    logger.error("attach port to cloud server fail:", e);
                    resourceEventPublisher.send(message);
                }
            }).start();
            return new BocloudResult<>(true, "挂载网卡任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("openstack CloudServer mount network fail:", e);
            return new BocloudResult<>(false, "网卡挂载失败：" + e.getMessage());
        }

    }

    @Override
    public BocloudResult detachNetwork(Long id, Long portId, RequestContext context) {
        String path = CloudServer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            // 虚拟机
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            Long vendorId = server.getVendorId();
            // 云供应商
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            Port port = portRepository.query(portId);
            Optional.ofNullable(port).orElseThrow(() -> new Exception("端口不存在"));
            if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
                // 获取一下RMC状态，不活动的话就不允许附加网卡
                if (!BocloudStatus.Server.STOPPED.name().equals(server.getStatus())) {
                    BocloudResult serverResult = serverDriver.detail(server.getInstanceId(), vendor.getUuid(), null);
                    if (serverResult.isFailed()) {
                        return new BocloudResult<>(false, "获取虚拟机详情失败：" + serverResult.getMessage());
                    }
                    ServerModel serverModel = (ServerModel)serverResult.getData();
                    String rmcStatus = JSON.parseObject(serverModel.getProps()).getString("rmcStatus");
                    if (!"active".equals(rmcStatus)) {
                        return new BocloudResult<>(false, "该虚拟机不具备有效RMC连接，您可以关闭该虚拟机或将该虚拟机的RMC连接进入活动状态后再试！");
                    }
                }
                new Thread(() -> {
                    String operate = vendor.getType().toLowerCase() + ".vm";
                    OperateResult message = new OperateResult(false, "网卡卸载失败", operate,
                        MapTools.simpleMap(Common.VENDORID, vendorId), OperateCategory.ResourceEvent, context);
                    try {
                        BocloudResult detachResult = serverDriver.detachNetwork(vendor.getUuid(), null,
                            server.getInstanceId(), port.getPortUuid());
                        ResourceEvent event =
                            new ResourceEvent(server.getId(), "网卡卸载", detachResult.isSuccess() ? "成功" : "失败",
                                context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                        resourceEventRepository.save(event);
                        if (detachResult.isFailed()) {
                            message.setSuccess(false);
                            message.setMessage(detachResult.getMessage());
                            resourceEventPublisher.send(message);
                            return;
                        }
                        ipRepository.deleteByPortId(port.getId());
                        portFixedIpRepository.deleteByPortId(port.getId());
                        portRepository.remove(port.getId(), context.getTarget());
                        if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
                            ServerModel model = (ServerModel)detachResult.getData();
                            powervcTransportor.insertOrUpdate(vendor, model, context.getTarget());
                        }
                        message.setSuccess(true);
                        message.setMessage("网卡卸载成功");
                        resourceEventPublisher.send(message);
                    } catch (Exception e) {
                        logger.error("attach port to cloud server fail:", e);
                        resourceEventPublisher.send(message);
                    }
                }).start();
                return new BocloudResult<>(true, "卸载网卡任务已下发，正在执行...");

            } else {
                BocloudResult result =
                    serverDriver.detachNetwork(vendor.getUuid(), null, server.getInstanceId(), port.getPortUuid());
                if (result.isFailed()) {
                    return new BocloudResult<>(false, result.getMessage());
                }
                // 更新端口记录
                boolean flag = portRepository.remove(port.getId(), context.getTarget());
                if (flag) {
                    server.setPrivateIps(serverOperationHelper.getPrivateIps(server, vendor));
                    cloudServerRepository.update(server);
                    ResourceEvent event = new ResourceEvent(server.getId(), "网卡卸载", result.isSuccess() ? "成功" : "失败",
                        context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                    resourceEventRepository.save(event);
                    // 同步资源表
                    serverOperationHelper.syncOsVResource(vendor.getId(), server, context.getTarget());
                    List<PortFixedIp> fixedIps = portFixedIpRepository.listByPortId(portId);
                    for (PortFixedIp fixedIp : fixedIps) {
                        // 回收IP
                        ipRepository.delete(fixedIp.getIpAddress(), fixedIp.getSubnetId(), vendor.getId());
                    }
                    cloudServerRepository.update(server);
                    portFixedIpRepository.deleteByPortId(portId);
                    // 更新浮动IP记录
                    FloatingIp fip = floatingIpRepository.getByPortId(port.getId());
                    if (null != fip) {
                        fip.setFixedIpAddress(null);
                        fip.setPortUuid(null);
                        fip.setPortId(null);
                        fip.setRouterUuid(null);
                        fip.setRouterId(null);
                        fip.setStatus("STOPPED");
                        floatingIpRepository.update(fip);
                    }
                }
                return new BocloudResult<>(true, "网卡卸载成功");
            }
        } catch (Exception e) {
            logger.error("openstack CloudServer uninstall network fail:", e);
            return new BocloudResult<>(false, "网卡卸载失败");
        }
    }

    @Override
    public BocloudResult detachAllPorts(Long id, RequestContext context) {
        try {
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            List<Port> ports = portRepository.listByDeviceId(server.getInstanceId(), server.getVendorId());
            for (Port port : ports) {
                this.detachNetwork(id, port.getId(), context);
            }
            return new BocloudResult<>(true, "网卡卸载成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "网卡卸载失败");
        }
    }

    public Flavor getFlavorId(JSONObject params) {
        Long cpu = params.getLong("cpu");
        Long memory = params.getLong("memory");
        Long vendorId = params.getLong("vendorId");
        if (null == cpu || null == memory) {
            return null;
        }
        List<Param> parameter = Lists.newArrayList();
        // 匹配
        parameter.add(new Param(MapTools.simpleMap("cpu", cpu), Sign.EQ));
        parameter.add(new Param(MapTools.simpleMap("memory", memory), Sign.EQ));
        parameter.add(new Param(MapTools.simpleMap("family", "CPU_V5_GC"), Sign.EQ));
        parameter.add(new Param(MapTools.simpleMap(Common.VENDORID, vendorId), Sign.EQ));
        // 排序
        Map<String, String> sorter = new HashMap<>(8);
        sorter.put("cpu", "0");
        List<Flavor> flavors = flavorRepository.list(parameter, sorter);
        if (ListTool.isEmpty(flavors) || null == flavors.get(0)) {
            return null;
        }
        return flavors.get(0);
    }

    @Override
    public BocloudResult resize(String params, RequestContext context) {
        JSONObject object = JSONTools.isJSONObj(params);
        if (null == object) {
            return new BocloudResult<>(false, "参数格式错误");
        }
        // 虚拟机ID
        Long id = object.getLong(Common.ID);
        // 云平台ID
        Long vendorId = object.getLong(Common.VENDORID);
        // 规格ID
        Long flavorId = object.getLong("flavorId");
        Boolean forceStop = object.getBoolean("forceStop") == null ? false : object.getBoolean("forceStop");
        String path = CloudServer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            // 云供应商
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            // 虚拟机
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            String serverStatus = server.getStatus();
            // powervc和openstack可以在开机的状态下调整配置
            if (!forceStop && !(CloudProvider.OPENSTACK.name().equals(vendor.getType())
                || CloudProvider.POWERVC.name().equals(vendor.getType())
                || CloudProvider.AZURE.name().equals(vendor.getType()))) {
                if ("RUNNING".equalsIgnoreCase(server.getStatus())) {
                    return new BocloudResult<>(false, "配置调整需要在关机状态下操作!");
                }
            }
            // 规格
            Flavor flavor = null;
            if (CloudProvider.TIANYI.name().equals(vendor.getType())) {
                flavor = getFlavorId(JSONObject.parseObject(params));
            } else {
                flavor = flavorRepository.query(flavorId);
            }
            Optional.ofNullable(flavor).orElseThrow(() -> new Exception("规格不存在"));
            if (CloudProvider.TIANYI.name().equals(vendor.getType())
                || CloudProvider.HUAWEI.name().equals(vendor.getType())
                || CloudProvider.FUSIONCLOUD.name().equals(vendor.getType())
                || CloudProvider.MANAGEONE.name().equals(vendor.getType())
                || CloudProvider.QCLOUD.name().equals(vendor.getType())
                || CloudProvider.PQCLOUD.name().equals(vendor.getType())
                || CloudProvider.TCE.name().equals(vendor.getType())
                || CloudProvider.AZURE.name().equals(vendor.getType())
                || CloudProvider.AWS.name().equals(vendor.getType())
                || CloudProvider.ALIYUN.name().equals(vendor.getType())
                || CloudProvider.TENCENT.name().equals(vendor.getType())) {
                // 支持 高配 --> 低配 所以不做判断处理
            } else if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
                // 获取一下RMC状态，不活动的话就不允许调整大小
                if (!BocloudStatus.Server.STOPPED.name().equals(server.getStatus())) {
                    BocloudResult bocloudResult = serverDriver.detail(server.getInstanceId(), vendor.getUuid(), null);
                    if (bocloudResult.isFailed()) {
                        return new BocloudResult<>(false, "获取虚拟机详情失败：" + bocloudResult.getMessage());
                    }
                    ServerModel serverModel = (ServerModel)bocloudResult.getData();
                    String rmcStatus = JSON.parseObject(serverModel.getProps()).getString("rmcStatus");
                    if (!"active".equals(rmcStatus)) {
                        return new BocloudResult<>(false, "该虚拟机不具备有效RMC连接，您可以关闭该虚拟机或将该虚拟机的RMC连接进入活动状态后再试！");
                    }
                }
                FlavorExtraSpecs flavorExtraSpecs = flavorExtraSpecsRepository.query(flavor.getExtraSpecsId());
                Optional.ofNullable(flavorExtraSpecs).orElseThrow(() -> new Exception("规格扩展信息不存在"));
                flavor.setExtraSpecs(flavorExtraSpecs);
                // 获取填写的具体数字
                if (object.get("flavor") != null) {
                    JSONObject flavorObject = object.getJSONObject("flavor");
                    flavor.setCpu(flavorObject.getInteger("cpu"));
                    flavor.setMemory(flavorObject.getBigDecimal("memory"));
                    if (flavorObject.get("hmcCpu") != null) {
                        flavorExtraSpecs.setProcUnits(flavorObject.getDouble("hmcCpu"));
                    } else {
                        flavorExtraSpecs.setProcUnits(0.5);
                    }
                }
                // 2019-07-17 : 将来计算模板支持高级设定，该if判断就不需要了
                if (server.getCpu().equals(flavor.getCpu()) && server.getMemory().compareTo(flavor.getMemory()) == 0
                    && server.getHmcCpu().equals(flavorExtraSpecs.getProcUnits())) {
                    return new BocloudResult<>(false, "依照当前填写的配置，该虚拟机无需做任何更改，请重新填写！");
                }
                Flavor oldFlavor = flavorRepository.getByFlavorUuid(server.getFlavorUuid());
                Optional.ofNullable(oldFlavor).orElseThrow(() -> new Exception("虚拟机规格不存在"));
                FlavorExtraSpecs oldFlavorExtraSpecs = flavorExtraSpecsRepository.query(oldFlavor.getExtraSpecsId());
                Optional.ofNullable(oldFlavorExtraSpecs).orElseThrow(() -> new Exception("虚拟机规格扩展信息不存在"));
                if ((null != oldFlavorExtraSpecs.getMinProcUnits()
                    && flavorExtraSpecs.getProcUnits() < oldFlavorExtraSpecs.getMinProcUnits())
                    || (null != oldFlavorExtraSpecs.getMaxProcUnits()
                        && flavorExtraSpecs.getProcUnits() > oldFlavorExtraSpecs.getMaxProcUnits())) {
                    return new BocloudResult<>(false, String.format("虚拟处理单元数需要在%.2f到%.2f之间",
                        oldFlavorExtraSpecs.getMinProcUnits(), oldFlavorExtraSpecs.getMaxProcUnits()));
                }
                if ((null != oldFlavorExtraSpecs.getMinVcpu() && flavor.getCpu() < oldFlavorExtraSpecs.getMinVcpu())
                    || (null != oldFlavorExtraSpecs.getMaxVcpu()
                        && flavor.getCpu() > oldFlavorExtraSpecs.getMaxVcpu())) {
                    return new BocloudResult<>(false, String.format("虚拟处理器数需要在%d到%d之间",
                        oldFlavorExtraSpecs.getMinVcpu(), oldFlavorExtraSpecs.getMaxVcpu()));
                }
                if ((null != oldFlavorExtraSpecs.getMinMem()
                    && flavor.getMemory().compareTo(oldFlavorExtraSpecs.getMinMem()) < 0)
                    || (null != oldFlavorExtraSpecs.getMaxMem()
                        && flavor.getMemory().compareTo(oldFlavorExtraSpecs.getMaxMem()) > 0)) {
                    return new BocloudResult<>(false, String.format("内存大小需要在%.4fGB到%.4fGB之间",
                        oldFlavorExtraSpecs.getMinMem().doubleValue(), oldFlavorExtraSpecs.getMaxMem().doubleValue()));
                }
                if (flavor.getMemory().multiply(new BigDecimal(1024)).longValue() % 64 != 0) {
                    return new BocloudResult<>(false, "内存大小需要是64MB的整数倍");
                }
                if (flavor.getCpu() / flavorExtraSpecs.getProcUnits() > 10
                    || flavor.getCpu() / flavorExtraSpecs.getProcUnits() < 1) {
                    return new BocloudResult<>(false, "虚拟处理器数和处理单元数的比值需在1-10之间");
                }
                // 判断主机资源是否满足当前调整需求
                if (flavorExtraSpecs.getProcUnits() > server.getHmcCpu()
                    || flavor.getMemory().compareTo(server.getMemory()) > 0) {
                    Server host = serverRepository.query(server.getHostId());
                    Optional.ofNullable(host).orElseThrow(() -> new Exception("目标宿主机不存在"));
                    ServerConfig serverConfig = serverConfigRepository.getBySid(server.getHostId());
                    Optional.ofNullable(serverConfig).orElseThrow(() -> new Exception("目标宿主机配置不存在"));
                    double needProcUnit = flavorExtraSpecs.getProcUnits() - server.getHmcCpu();
                    double freeProcUnit =
                        serverConfig.getHmcCpu() - serverConfig.getHmcCpuReserved() - serverConfig.getHmcCpuUsed();
                    if (needProcUnit > freeProcUnit) {
                        return new BocloudResult<>(false,
                            String.format("cpu资源不足，本次调整额外需要%.2f个处理器单元，当前主机剩余%.2f个处理器单元", needProcUnit, freeProcUnit));
                    }
                    double needMemory = flavor.getMemory().subtract(server.getMemory()).longValue();
                    double freeMemory =
                        serverConfig.getMemoryCapacity() - serverConfig.getMemReserved() - serverConfig.getMemUsed();
                    if (needMemory > freeMemory) {
                        return new BocloudResult<>(false,
                            String.format("内存资源不足，本次调整额外需要%.4fGB内存，当前主机剩余%.4fGB内存", needMemory, freeMemory));
                    }
                }
            } else {
                // 新配置的CPU，磁盘，内存不能小于原配置
                if (flavor.getCpu() < server.getCpu() || flavor.getDisk() < server.getDisk()
                    || (flavor.getMemory().compareTo(server.getMemory()) < 0)) {
                    return new BocloudResult<>(false, "CPU、磁盘和内存大小不能小于原配置");
                }
            }

            // 更新虚拟机的状态为正在调整大小 - RESIZED
            if (CloudProvider.FUSIONCLOUD.name().equals(vendor.getType())
                || CloudProvider.OPENSTACK.name().equals(vendor.getType())
                || CloudProvider.MANAGEONE.name().equals(vendor.getType())) {
                // VERIFYRESIZE 修改配置中 需要确认或 回滚
                server.setStatus(BocloudStatus.Server.RESIZING.name());
            } else {
                server.setStatus(BocloudStatus.Server.VERIFYRESIZE.name());
            }
            cloudServerRepository.update(server);
            Flavor finalFlavor = flavor;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String operate = vendor.getType().toLowerCase() + ".vm";
                    OperateResult message = new OperateResult(false, "配置修改失败", operate,
                        MapTools.simpleMap(Common.VENDORID, vendorId), OperateCategory.ResourceEvent, context);
                    try {
                        // 修改配置
                        BocloudResult result = new BocloudResult<>();
                        if (CloudProvider.TENCENT.name().equals(vendor.getType())
                            || CloudProvider.TCE.name().equals(vendor.getType())) {
                            result = serverDriver.resize(server.getInstanceId(), finalFlavor.getFlavorUuid(), forceStop,
                                vendor.getUuid(), server.getRegionId());
                        } else if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
                            result = serverDriver.resize(
                                JSONObject.parseObject(JSONObject.toJSONString(server), ServerModel.class),
                                JSONObject.parseObject(JSONObject.toJSONString(finalFlavor), FlavorModel.class),
                                vendor.getUuid(), server.getRegionId());
                        } else {
                            result = serverDriver.resize(server.getInstanceId(), finalFlavor.getFlavorUuid(),
                                vendor.getUuid(), server.getRegionId());
                        }
                        CloudServer server = cloudServerRepository.query(id);
                        if (result.isSuccess()) {
                            if (CloudProvider.FUSIONCLOUD.name().equals(vendor.getType())
                                || CloudProvider.MANAGEONE.name().equals(vendor.getType())
                                || CloudProvider.OPENSTACK.name().equals(vendor.getType())) {
                                message.setMessage("操作成功，请确认或取消修改配置！");
                            } else {
                                message.setMessage("配置修改成功");
                            }
                            message.setSuccess(true);
                            // 更新配置
                            ServerModel model = serverOperationHelper.parseObject(result.getData(), ServerModel.class);
                            if (model.getStatus().equals(BocloudStatus.Server.ERROR.name())) {
                                server.setStatus(BocloudStatus.Server.EXCEPTION.name());
                            } else {
                                server.setStatus(model.getStatus());
                            }
                            server.setCpu(finalFlavor.getCpu());
                            server.setMemory(finalFlavor.getMemory());
                            server.setFlavorName(finalFlavor.getName());
                            server.setFlavorUuid(finalFlavor.getFlavorUuid());
                            if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
                                server.setHmcCpu(finalFlavor.getExtraSpecs().getProcUnits());
                                // 更新任务状态
                                JSONObject props = StringUtils.isEmpty(server.getProps()) ? new JSONObject()
                                    : JSON.parseObject(server.getProps());
                                props.remove("taskStatus");
                                server.setProps(props.toJSONString());
                            } else if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
                                server.setStatus("STOPPED");
                            }
                            cloudServerRepository.update(server);
                            // 判断是否需要更新运营订单，因为公有云不计费，但是需要更新订单
                            String uuid = server.getUuid();
                            if (!StringUtils.isEmpty(uuid)) {
                                OrderItem item = cosInternalService.queryByItemSn(uuid);
                                if (null != item) {
                                    // 生成新订单，废弃旧订单
                                    String elements = item.getElements();
                                    List<ElementModel> elementModels = new ArrayList<>();
                                    if (!StringUtils.isEmpty(elements)) {
                                        elementModels = JSONArray.parseArray(elements, ElementModel.class);
                                        for (ElementModel elementModel : elementModels) {
                                            List<SpecModel> specs = elementModel.getSpecs();
                                            if (ListTool.isEmpty(specs)) {
                                                continue;
                                            }
                                            if (specs.size() == 3) {
                                                for (SpecModel spec : specs) {
                                                    if (null != spec.getCpu()) {
                                                        spec.setCpu(server.getCpu());
                                                    }
                                                    if (null != spec.getMemory()) {
                                                        spec.setMemory(server.getMemory());
                                                    }
                                                    if (null != spec.getDisk()) {
                                                        spec.setDisk(server.getDisk());
                                                    }
                                                }
                                            }
                                            elementModel.setSpecs(specs);
                                        }
                                        // 更新订单明细
                                        // BocloudResult bocloudResult = cosInternalService.updateElements(uuid,
                                        // elementModels);
                                        // logger.info("升级规格更细订单明细结果:{}", JSONObject.toJSON(bocloudResult));
                                    }
                                    // 创建新订单
                                    OrderItem newItem = new OrderItem();
                                    newItem.setOrderId(item.getOrderId());
                                    newItem.setSkuId(item.getSkuId());
                                    newItem.setServiceCode(item.getServiceCode());
                                    newItem.setStatus(OrderItemStatus.ChangeSuccess);
                                    newItem.setDuration(item.getDuration());
                                    newItem.setEffectiveTime(new Date());
                                    newItem.setExpiredTime(item.getExpiredTime());
                                    newItem.setResources(item.getResources());
                                    newItem.setElements(JSONObject.toJSONString(elementModels));
                                    newItem.setInventory(item.getInventory());
                                    newItem = cosInternalService.createOrderItem(newItem);
                                    if (null != newItem) {
                                        logger.info("变更产生的订单明细：{}", JSONObject.toJSON(newItem));
                                        // 废弃旧订单
                                        BocloudResult bocloudResult =
                                            cosInternalService.updateItemStatus(uuid, OrderItemStatus.Abandoned.name());
                                        logger.info("废弃原订单结果：{}", JSONObject.toJSON(bocloudResult));
                                    }
                                }
                            }
                        } else {
                            if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
                                // 调整大小失败后更新虚拟机状态为错误
                                server.setStatus(BocloudStatus.Server.ERROR.name());
                                // 更新任务状态
                                JSONObject props = StringUtils.isEmpty(server.getProps()) ? new JSONObject()
                                    : JSON.parseObject(server.getProps());
                                props.remove("taskStatus");
                                server.setProps(props.toJSONString());
                                cloudServerRepository.update(server);
                            } else {
                                server.setStatus(serverStatus);
                                cloudServerRepository.update(server);
                            }
                            message.setMessage(message.getMessage() + ":" + result.getMessage());
                        }
                        ResourceEvent event =
                            new ResourceEvent(server.getId(), "规格变更", result.isSuccess() ? "成功" : "失败",
                                context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                        resourceEventRepository.save(event);
                    } catch (Exception e) {
                        server.setStatus(serverStatus);
                        cloudServerRepository.update(server);
                        logger.error("CloudServer resize error:", e);
                    }
                    resourceEventPublisher.send(message);
                }
            }).start();
            if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
                // 更改虚拟机的任务状态，一定要放在最后
                JSONObject props =
                    StringUtils.isEmpty(server.getProps()) ? new JSONObject() : JSON.parseObject(server.getProps());
                props.put("taskStatus", "resized");
                server.setProps(props.toJSONString());
                cloudServerRepository.update(server);
            }
            return new BocloudResult<>(true, "修改配置任务已下发，请勿进行其他操作...");
        } catch (Exception e) {
            logger.error("CloudServer resize error:", e);
            return new BocloudResult<>(false, "修改配置失败 :" + e.getMessage());
        }
    }

    @Override
    public BocloudResult confirmResize(String params, RequestContext context) {
        JSONObject object = JSONTools.isJSONObj(params);
        if (null == object) {
            return new BocloudResult<>(false, "参数格式错误");
        }
        // 虚拟机ID
        Long id = object.getLong(Common.ID);
        String path = CloudServer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            // 虚拟机
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            // 云供应商
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".vm";
                OperateResult message = new OperateResult(false, "配置确认失败", operate,
                    MapTools.simpleMap(Common.VENDORID, vendor.getId()), OperateCategory.ResourceEvent, context);
                try {
                    BocloudResult result =
                        serverDriver.confirmResize(server.getInstanceId(), vendor.getUuid(), server.getRegionId());
                    if (result.isSuccess()) {
                        message.setMessage("配置确认成功");
                        message.setSuccess(true);
                        // 更新
                        ServerModel model = serverOperationHelper.parseObject(result.getData(), ServerModel.class);
                        if (model.getStatus().equals(BocloudStatus.Server.ERROR.name())) {
                            server.setStatus(BocloudStatus.Server.EXCEPTION.name());
                        } else {
                            server.setStatus(model.getStatus());
                        }
                        String flavorUuid = model.getFlavorUuid();
                        if (null != flavorUuid && !"".equals(flavorUuid)) {
                            server.setFlavorUuid(flavorUuid);
                            List<Volume> listByServerId =
                                volumeRepository.listByServerId(server.getId(), vendor.getId(), true);
                            if (null == listByServerId || listByServerId.size() == 0) {
                                server.setDisk(model.getDisk());
                            }
                        }
                        cloudServerRepository.update(server);
                        // 同步到cmdb
                        List<CmdbInfo> infos = Lists.newArrayList();
                        infos.add(CmdbInfoConvertor.getInfo(server, "modify", null));
                        cmdbMessagePublisher.send(CmdbInfoConvertor.getModel(BoCloudService.IMS, infos));
                    } else {
                        message.setMessage(message.getMessage() + ":" + result.getMessage());
                    }
                    resourceEventPublisher.send(message);
                } catch (Exception e) {
                    logger.error("CloudServer revert resize error:", e);
                    resourceEventPublisher.send(message);
                }
            }).start();
            return new BocloudResult<>(true, "确认修改配置任务已经下发...");
        } catch (Exception e) {
            logger.error("openstack cloudServer confirm resize error:", e);
            return new BocloudResult<>(false, "修改配置失败");
        }
    }

    @Override
    public BocloudResult revertResize(String params, RequestContext context) {
        JSONObject object = JSONTools.isJSONObj(params);
        if (null == object) {
            return new BocloudResult<>(false, "参数格式错误");
        }
        // 虚拟机ID
        Long id = object.getLong(Common.ID);
        String path = CloudServer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            // 虚拟机
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            // 云供应商
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".vm";
                OperateResult message = new OperateResult(false, "配置回滚失败", operate,
                    MapTools.simpleMap(Common.VENDORID, vendor.getId()), OperateCategory.ResourceEvent, context);
                try {
                    // 回滚配置
                    BocloudResult result =
                        serverDriver.revertResize(server.getInstanceId(), vendor.getUuid(), server.getRegionId());
                    // 更新
                    if (result.isSuccess()) {
                        message.setMessage("配置回滚成功");
                        message.setSuccess(true);
                        ServerModel model = serverOperationHelper.parseObject(result.getData(), ServerModel.class);
                        if (model.getStatus().equals(BocloudStatus.Server.ERROR.name())) {
                            server.setStatus(BocloudStatus.Server.EXCEPTION.name());
                        } else {
                            server.setStatus(model.getStatus());
                        }
                        if (CloudProvider.FUSIONCLOUD.name().equals(vendor.getType())
                            || CloudProvider.MANAGEONE.name().equals(vendor.getType())
                            || CloudProvider.HUAWEI.name().equals(vendor.getType())) {
                            List<Volume> volumes = volumeRepository.listByServerId(server.getId());
                            int disk = 0;
                            for (Volume volume : volumes) {
                                if ("/dev/vda".equals(volume.getDevice()) || "/dev/sda".equals(volume.getDevice())) {
                                    disk += volume.getSize();
                                }
                            }
                            server.setDisk(disk);
                            // FusionCloud返回值中没有cpu memory信息
                            String flavorUuid = model.getFlavorUuid();
                            Flavor flavor = flavorRepository.getByFlavorId(flavorUuid);
                            if (null != flavor) {
                                server.setCpu(flavor.getCpu());
                                server.setMemory(flavor.getMemory());
                            }
                        } else {
                            server.setCpu(model.getCpu());
                            server.setMemory(model.getMemory());
                            server.setDisk(model.getDisk());
                            server.setFlavorUuid(model.getFlavorUuid());
                        }
                        cloudServerRepository.update(server);
                        // 同步到cmdb
                        List<CmdbInfo> infos = Lists.newArrayList();
                        infos.add(CmdbInfoConvertor.getInfo(server, "modify", null));
                        cmdbMessagePublisher.send(CmdbInfoConvertor.getModel(BoCloudService.IMS, infos));
                    } else {
                        message.setMessage(message.getMessage() + ":" + result.getMessage());
                    }
                    resourceEventPublisher.send(message);
                } catch (Exception e) {
                    logger.error("CloudServer revert resize error:", e);
                    resourceEventPublisher.send(message);
                }
            }).start();
            return new BocloudResult<>(true, "回滚配置任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("openstack cloudServer revert resize error:", e);
            return new BocloudResult<>(false, "回滚配置失败");
        }
    }

    @Override
    public BocloudResult<List<Flavor>> listFlavor(Long serverId, Long vendorId) {
        try {
            CloudServer server = cloudServerRepository.query(serverId);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            // 云供应商
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            List<Flavor> flavors = null;
            if (CloudProvider.HUAWEI.name().equals(vendor.getType())
                || CloudProvider.TENCENT.name().equals(vendor.getType())) {
                flavors = flavorRepository.listByVendorId(vendorId, server.getRegionId());
            } else {
                flavors = flavorRepository.listByVendorId(vendorId);
            }
            if (ListTool.isEmpty(flavors)) {
                return new BocloudResult<>(false, "云平台下没有可适配的规格");
            }
            List<Flavor> result = Lists.newArrayList();
            for (Flavor flavor : flavors) {
                if (CloudProvider.HUAWEI.name().equals(vendor.getType())) {
                    // 华为云 支持高配 --> 低配 所以这不做判断处理
                    String zoneId = server.getZone();
                    List<String> flavorList = JSONObject.parseArray(flavor.getZone(), String.class);
                    if (flavorList.contains(zoneId)) {
                        result.add(flavor);
                    }
                } else if (CloudProvider.TIANYI.name().equals(vendor.getType())) {
                    // 天翼云 支持高配 --> 低配 所以这不做判断处理
                    if (flavor.getFlavorUuid() != server.getFlavorUuid()
                        && !flavor.getFlavorUuid().equals(server.getFlavorUuid())) {
                        String zoneId = server.getZone();
                        List<String> flavorList = JSONObject.parseArray(flavor.getZone(), String.class);
                        for (String zone : flavorList) {
                            String replace = zone.replace("(normal)", "");
                            if (replace == zoneId || replace.equals(zoneId)) {
                                result.add(flavor);
                            }
                        }
                    }
                } else if (CloudProvider.FUSIONCLOUD.name().equals(vendor.getType())
                    || CloudProvider.MANAGEONE.name().equals(vendor.getType())) {
                    result = flavors;
                } else {
                    List<Flavor> list = Lists.newArrayList();
                    if (flavor.getCpu() >= server.getCpu() && flavor.getDisk() >= server.getDisk()
                        && flavor.getMemory().compareTo(server.getMemory()) >= 0) {
                        list.add(flavor);
                    }
                    String spec = server.getCpu() + "C" + server.getMemory() + "GB" + server.getDisk() + "GB";
                    for (Flavor f : list) {
                        if (!spec.equalsIgnoreCase(f.getCpu() + "C" + f.getMemory() + "GB" + f.getDisk() + "GB")) {
                            result.add(f);
                        }
                    }
                }
            }
            return new BocloudResult<>(true, result, "查询成功");
        } catch (Exception e) {
            logger.error("list flavor error：", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult<List<Port>> listPort(Long serverId, Long vendorId) {
        try {
            // 云供应商
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            // 虚拟机
            CloudServer server = cloudServerRepository.query(serverId);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            List<Port> ports = portRepository.listByDeviceId(server.getInstanceId(), server.getVendorId());
            return new BocloudResult<>(true, ports, "查询成功!");
        } catch (Exception e) {
            logger.error("list vm port failure:", e);
            return new BocloudResult<>(false, "查询失败!");
        }
    }

    @Override
    public BocloudResult<Flavor> queryFlavorByServerId(Long serverId) {
        try {
            CloudServer server = cloudServerRepository.query(serverId);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            Flavor flavor = flavorRepository.getByFlavorUuid(server.getFlavorUuid());
            return new BocloudResult<>(true, flavor, "查询成功");
        } catch (Exception e) {
            logger.info("query server flavor error:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult hotConfigEnable(Long serverId, Long userId, Boolean cpuHotEnable, Boolean memHotEnable) {
        try {
            CloudServer cloudServer = cloudServerRepository.query(serverId);
            Optional.ofNullable(cloudServer).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(cloudServer.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            // 非关机状态不允许对cpu或内存进行热插拔设置
            if (!cloudServer.getStatus().equals(BocloudStatus.Server.STOPPED.name())) {
                return new BocloudResult<>(false, "非关机状态不允许对cpu或内存进行热插拔设置!");
            }
            BocloudResult result = serverDriver.hotConfigEnable(cloudServer.getInstanceId(), cpuHotEnable, memHotEnable,
                vendor.getUuid(), null);
            if (result.isFailed()) {
                return result;
            }
            cloudServer.setCpuHotEnable(cpuHotEnable);
            cloudServer.setMemHotEnable(memHotEnable);
            boolean flag = cloudServerRepository.update(cloudServer);
            if (flag) {
                // 同步到cmdb
                List<CmdbInfo> infos = Lists.newArrayList();
                infos.add(CmdbInfoConvertor.getInfo(cloudServer, "modify", null));
                cmdbMessagePublisher.send(CmdbInfoConvertor.getModel(BoCloudService.IMS, infos));
                return new BocloudResult<>(true, "热插拔设置成功!");
            }
            return new BocloudResult<>(true, "热插拔设置失败!");
        } catch (Exception e) {
            logger.error("Get error message:", e);
            return new BocloudResult<>(false, "热插拔设置失败!");
        }
    }

    @Override
    public BocloudResult getTicket(Long serverId) {
        try {
            CloudServer server = cloudServerRepository.query(serverId);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            BocloudResult result = serverDriver.getTicket(server.getInstanceId(), vendor.getUuid(), null);
            return result.isFailed() ? result : new BocloudResult<>(true, result.getData(), "获取ticket成功");
        } catch (Exception e) {
            logger.error("Get error message", e);
            return new BocloudResult<>(false, "获取ticket失败");
        }
    }

    @Override
    public BocloudResult unmountToolsInstaller(Long id) {
        try {
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            BocloudResult result = serverDriver.unmountToolsInstaller(server.getInstanceId(), vendor.getUuid(), null);
            return result.isFailed() ? result : new BocloudResult<>(true, "卸载vmware tools安装镜像成功");
        } catch (Exception e) {
            logger.error("Get error message:", e);
            return new BocloudResult<>(false, "卸载vmware tools安装镜像失败");
        }
    }

    @Override
    public BocloudResult upgradeToolsTask(Long id, String options, RequestContext context) {
        try {
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            if (!BocloudStatus.Server.RUNNING.name().equals(server.getStatus())) {
                logger.warn("Change state does not support this operation");
                return new BocloudResult<>(false, "该状态不支持此操作");
            }
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".vm";
                BocloudResult result =
                    serverDriver.upgradeToolsTask(server.getInstanceId(), options, vendor.getUuid(), null);
                resourceEventPublisher.send(new OperateResult(result.isSuccess(), result.getMessage(), operate,
                    MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
            }).start();
            return new BocloudResult<>(true, "挂载或升级vmware tools任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("Get error message:", e);
            return new BocloudResult<>(false, "挂载或升级vmware tools失败");
        }
    }

    @Override
    public BocloudResult chart(String params) {
        JSONObject object = JSONObject.parseObject(params);
        try {
            Optional.ofNullable(object).orElseThrow(() -> new Exception("参数格式错误"));
            String catalog = StringUtils.isEmpty(object.getString("catalog")) ? "VENDOR" : object.getString("catalog");
            if ("VENDOR".equals(catalog)) {
                List<CloudVendor> vendors = cloudVendorRepository.listByType(null);
                List<String> keys = Lists.newArrayList();
                List<String> datas = Lists.newArrayList();
                for (CloudVendor vendor : vendors) {
                    keys.add(vendor.getName());
                    List<CloudServer> cloudServers = cloudServerRepository.listByVendorId(vendor.getId());
                    datas.add(String.valueOf(cloudServers.size()));
                }
                TrendData trendData = new TrendData("虚拟机个数", datas);
                List<TrendData> values = Lists.newArrayList();
                values.add(trendData);
                ResultTrend resultTrend = new ResultTrend(keys, values);
                return new BocloudResult<>(true, resultTrend, "查询成功");
            } else if ("CLUSTER".equals(catalog)) {
                List<Cluster> clusters = clusterRepository.listByType(null);
                List<String> keys = Lists.newArrayList();
                List<String> datas = Lists.newArrayList();
                for (Cluster cluster : clusters) {
                    keys.add(cluster.getName());
                    int vmNum = cloudServerRepository.count(cluster.getId(), new ArrayList<>());
                    datas.add(String.valueOf(vmNum));
                }
                TrendData trendData = new TrendData("虚拟机个数", datas);
                List<TrendData> values = Lists.newArrayList();
                values.add(trendData);
                ResultTrend resultTrend = new ResultTrend(keys, values);
                return new BocloudResult<>(true, resultTrend, "查询成功");
            }
            return new BocloudResult<>(true, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    /**
     * 虚拟机批量加入安全组
     */
    @Override
    public BocloudResult batchJoinSGroup(Long id, SecurityGroupOperationParam securityGroupOperationParam,
        RequestContext context) {
        String path = CloudServer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");

            Optional.ofNullable(securityGroupOperationParam).orElseThrow(() -> new Exception("参数格式错误"));
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            List<Long> groupIdsList = securityGroupOperationParam.getGroups();
            if (null == groupIdsList || groupIdsList.size() == 0) {
                return new BocloudResult<>(false, "参数格式错误");
            }
            // 查询虚拟机安全组关系
            List<ServerSgroup> sgroups = serverSgroupRepository.listByServerId(server.getId());
            Map<Long, ServerSgroup> sgroupMap = Maps.newHashMap();
            for (ServerSgroup sgroup : sgroups) {
                sgroupMap.put(sgroup.getGroupId(), sgroup);
            }
            new Thread(new Runnable() {
                @Override
                public void run() {
                    List<Long> successList = new ArrayList<>();
                    List<Long> failList = new ArrayList<>();
                    String operate = vendor.getType().toLowerCase() + ".vm";
                    String content = "";
                    try {
                        for (Long gourpId : groupIdsList) {
                            SecurityGroup group = securityGroupRepository.query(gourpId);
                            if (null == group) {
                                failList.add(gourpId);
                                content += "ID 【" + gourpId + "】 : 安全组不存在。\n";
                                continue;
                            }
                            String secuName = group.getName();
                            if (null != secuName && "Sys-default".equals(secuName)) {
                                secuName = "default";
                            }
                            BocloudResult bocloudResult = null;
                            if (CloudProvider.OPENSTACK.name().equalsIgnoreCase(vendor.getType())) {
                                TenantProvider provider =
                                    vendorProjectService.getAncestorProject(vendor.getId(), context.getTenant());
                                String projectName = null;
                                if (null != provider) {
                                    projectName = provider.getProjectName();
                                }
                                bocloudResult = serverDriver.joinSGroup(server.getInstanceId(), secuName,
                                    vendor.getUuid(), projectName, server.getRegionId());
                            } else {
                                bocloudResult = serverDriver.joinSGroup(server.getInstanceId(), secuName,
                                    vendor.getUuid(), server.getRegionId());
                            }
                            if (bocloudResult.isFailed()) {
                                failList.add(gourpId);
                                content += "名称【" + group.getName() + "】:" + bocloudResult.getMessage() + "\n";
                                continue;
                            }
                            successList.add(gourpId);
                            if (!sgroupMap.containsKey(group.getId())) {
                                ServerSgroup byServerGroup =
                                    serverSgroupRepository.getByServerGroup(server.getId(), group.getId());
                                if (null == byServerGroup) {
                                    ServerSgroup serverSgroup = new ServerSgroup(server.getId(), group.getId());
                                    serverSgroupRepository.save(serverSgroup);
                                }
                            }
                        }
                        String resultContent = "加入安全组成功【" + successList.size() + "】个,失败【" + failList.size() + "】个。";
                        if (failList.size() > 0) {
                            resultContent += "详情如下：\n" + content;
                        }
                        ResourceEvent event =
                            new ResourceEvent(server.getId(), "添加安全组", failList.size() == 0 ? "成功" : "失败",
                                context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                        resourceEventRepository.save(event);
                        resourceEventPublisher.send(new OperateResult(true, resultContent, operate,
                            MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                    } catch (Exception e) {
                        logger.error("添加安全组失败 ： " + e.getMessage());
                        resourceEventPublisher.send(new OperateResult(true, "加入安全组失败 ： " + e.getMessage(), operate,
                            MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                    }
                }
            }).start();
            return new BocloudResult<>(true, "加入安全组任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "加入安全组失败");
        }
    }

    @Override
    public BocloudResult joinSGroup(Long id, Long groupId, RequestContext context) {
        String path = CloudServer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            SecurityGroup group = securityGroupRepository.query(groupId);
            Optional.ofNullable(group).orElseThrow(() -> new Exception("安全组不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            if (CloudProvider.TENCENT.name().equals(vendor.getType())
                || CloudProvider.TCE.name().equals(vendor.getType())) {
                List<ServerSgroup> listByServerId = serverSgroupRepository.listByServerId(server.getId());
                if (null != listByServerId && listByServerId.size() > 0) {
                    for (ServerSgroup serverSgroup : listByServerId) {
                        if (serverSgroup.getGroupId().equals(group.getId())) {
                            return new BocloudResult<>(false, "该虚拟机、安全组已经绑定");
                        }
                    }
                }
            }
            BocloudResult result = null;
            if (CloudProvider.FUSIONCLOUD.name().equals(vendor.getType())) {
                result = serverDriver.joinSGroup(server.getInstanceId(), group.getName(), vendor.getUuid(),
                    server.getRegionId());
            } else if (CloudProvider.MANAGEONE.name().equals(vendor.getType())) {
                if (null != context.getTenant() && 0L != context.getTenant()) {
                    ManageOneAccount account = accountService.queryAccount(vendor.getId(), context.getTenant());
                    Assert.notNull(account, "认证失败！");
                    result = serverDriver.joinSGroup(vendor.getUuid(), account.getUsername(), account.getPassword(),
                        account.getProjectId(), account.getDomainName(), server.getInstanceId(), group.getName());
                } else {
                    result = serverDriver.joinSGroup(server.getInstanceId(), group.getName(), vendor.getUuid(),
                        server.getRegionId());
                }
            } else {
                result = serverDriver.joinSGroup(server.getInstanceId(), group.getGroupUuid(), vendor.getUuid(),
                    server.getRegionId());
            }
            if (result.isFailed()) {
                return new BocloudResult<>(false, result.getMessage());
            }
            if (CloudProvider.QCLOUD.name().equalsIgnoreCase(vendor.getType())
                || CloudProvider.PQCLOUD.name().equalsIgnoreCase(vendor.getType())) {
                serverSgroupRepository.removeBySid(server.getId());
            }
            List<ServerSgroup> sgroups = serverSgroupRepository.listByServerId(server.getId());
            Map<Long, ServerSgroup> sgroupMap = Maps.newHashMap();
            for (ServerSgroup sgroup : sgroups) {
                sgroupMap.put(sgroup.getGroupId(), sgroup);
            }
            if (!sgroupMap.containsKey(group.getId())) {
                ServerSgroup serverSgroup = new ServerSgroup(server.getId(), group.getId());
                serverSgroupRepository.save(serverSgroup);
            }
            ResourceEvent event = new ResourceEvent(server.getId(), "添加安全组", result.isSuccess() ? "成功" : "失败",
                context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
            resourceEventRepository.save(event);
            return new BocloudResult<>(true, "加入安全组成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "加入安全组失败");
        }
    }

    @Override
    public BocloudResult leaveSGroup(Long id, Long groupId, RequestContext context) {
        String path = CloudServer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            SecurityGroup group = securityGroupRepository.query(groupId);
            Optional.ofNullable(group).orElseThrow(() -> new Exception("安全组不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            if (CloudProvider.TENCENT.name().equals(vendor.getType())
                || CloudProvider.HUAWEI.name().equals(vendor.getType())
                || CloudProvider.TCE.name().equals(vendor.getType())
                || CloudProvider.ALIYUN.name().equals(vendor.getType())) {
                List<ServerSgroup> serverList = serverSgroupRepository.listByServerId(server.getId());
                if (null != serverList && serverList.size() == 1) {
                    return new BocloudResult<>(false, "该安全组不允许移除");
                }
            }
            BocloudResult result = null;
            if (CloudProvider.HUAWEI.name().equals(vendor.getType())) {
                // 华为显示 和 实际值不匹配
                String secuName = group.getName();
                if (null != secuName && "Sys-default".equals(secuName)) {
                    secuName = "default";
                }
                result =
                    serverDriver.leaveSGroup(server.getInstanceId(), secuName, vendor.getUuid(), server.getRegionId());
            } else if (CloudProvider.FUSIONCLOUD.name().equals(vendor.getType())) {
                String secuName = group.getName();
                result =
                    serverDriver.leaveSGroup(server.getInstanceId(), secuName, vendor.getUuid(), server.getRegionId());
            } else if (CloudProvider.MANAGEONE.name().equals(vendor.getType())) {
                String secuName = group.getName();
                if (null != context.getTenant() && 0L != context.getTenant()) {
                    ManageOneAccount account = accountService.queryAccount(vendor.getId(), context.getTenant());
                    Assert.notNull(account, "认证失败！");
                    result = serverDriver.leaveSGroup(vendor.getUuid(), account.getUsername(), account.getPassword(),
                        account.getProjectId(), account.getDomainName(), server.getInstanceId(), secuName);
                } else {
                    result = serverDriver.leaveSGroup(server.getInstanceId(), secuName, vendor.getUuid(),
                        server.getRegionId());
                }
            } else {
                if (CloudProvider.OPENSTACK.name().equalsIgnoreCase(vendor.getType())) {
                    String projectName = null;
                    OSTenant osTenant = osTenantRepository.getByTenantUuid(group.getTenantUuid(), vendor.getId());
                    if (null != osTenant) {
                        projectName = osTenant.getName();
                    }
                    result = serverDriver.leaveSGroup(server.getInstanceId(), group.getGroupUuid(), vendor.getUuid(),
                        projectName, server.getRegionId());
                } else {
                    result = serverDriver.leaveSGroup(server.getInstanceId(), group.getGroupUuid(), vendor.getUuid(),
                        server.getRegionId());
                }
            }
            if (result.isFailed()) {
                return new BocloudResult<>(false, "移除安全组失败");
            }
            serverSgroupRepository.remove(group.getId(), server.getId());
            ResourceEvent event = new ResourceEvent(server.getId(), "移除安全组", result.isSuccess() ? "成功" : "失败",
                context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
            resourceEventRepository.save(event);
            return new BocloudResult<>(true, "移除安全组成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "移除安全组失败");
        }
    }

    @Override
    public BocloudResult<List<SecurityGroup>> listSGroup(Long id) {
        try {
            List<ServerSgroup> serverSgroups = serverSgroupRepository.listByServerId(id);
            List<SecurityGroup> groups = Lists.newArrayList();
            for (ServerSgroup serverSgroup : serverSgroups) {
                SecurityGroup group = securityGroupRepository.query(serverSgroup.getGroupId());
                if (null != group) {
                    groups.add(group);
                }
            }
            return new BocloudResult<>(true, groups, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult<List<SecurityGroup>> listUnboundSGroup(Long id, RequestContext context) {
        try {
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            Map<Long, SecurityGroup> groupMap = new HashMap<>(8);
            List<ServerSgroup> serverSgroups = serverSgroupRepository.listByServerId(id);
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            Long tenantId = context.getTenant();
            // 为租户下的用户
            List<Long> projectIds = new ArrayList<>();
            List<SecurityGroup> groups = null;
            if (CloudProvider.HUAWEI.name().equals(vendor.getType())
                || CloudProvider.TENCENT.name().equals(vendor.getType())
                || CloudProvider.QCLOUD.name().equals(vendor.getType())) {
                groups = securityGroupRepository.listByVendorId(server.getVendorId(), server.getRegionId(), projectIds);
            } else if (CloudProvider.ALIYUN.name().equals(vendor.getType())) {
                groups = securityGroupRepository.listByVendorId(server.getVendorId(), server.getRegionId(), null);
                groups = groups.stream()
                    .filter(
                        group -> null != group.getVpcUuid() && group.getVpcUuid().equalsIgnoreCase(server.getVpcUuid()))
                    .collect(Collectors.toList());
            } else {
                groups =
                    securityGroupRepository.listByVendorId(server.getTenantUuid(), server.getVendorId(), projectIds);
            }
            // 过滤自服务安全组
			if (null != tenantId && 0 != tenantId) {
				groups = groups.stream().filter(group -> tenantId.equals(group.getTenantId()))
						.collect(Collectors.toList());
			}
            if (ListTool.isEmpty(serverSgroups)) {
                if (null != tenantId && 0L != tenantId) {
                    SimpleBean bean = securityGroupRepository.getDefaultSgroup(vendor.getId(), server.getTenantUuid());
                    if (null != bean) {
                        SecurityGroup defaultGroup = securityGroupRepository.query(bean.getId());
                        if (null != defaultGroup) {
                            groups.add(defaultGroup);
                        }
                    }
                }
                return new BocloudResult<>(true, groups, "查询成功");
            } else {
                Map<Long, Object> sGroupMap = Maps.newHashMap();
                for (ServerSgroup serverSgroup : serverSgroups) {
                    sGroupMap.put(serverSgroup.getGroupId(), serverSgroup);
                }
				if (CloudProvider.OPENSTACK.name().equals(vendor.getType())
						|| CloudProvider.MANAGEONE.name().equals(vendor.getType())
						|| CloudProvider.FUSIONCLOUD.name().equals(vendor.getType())) {
					SimpleBean bean = securityGroupRepository.getDefaultSgroup(vendor.getId(), server.getTenantUuid());
					if (null != bean) {
						SecurityGroup defaultGroup = securityGroupRepository.query(bean.getId());
						if (null != defaultGroup) {
							groups.add(defaultGroup);
						}
					}
				}
				for (SecurityGroup group : groups) {
                    if (!sGroupMap.containsKey(group.getId())) {
                        groupMap.put(group.getId(), group);
                    }
                }
            }
            return new BocloudResult<>(true, new ArrayList<>(groupMap.values()), "查询成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult markAsTemplate(Long id, RequestContext context) {
        try {
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            if (!BocloudStatus.Server.STOPPED.name().equals(server.getStatus())) {
                return new BocloudResult<>(false, "只能在关机状态下进行此操作");
            }
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            BocloudResult result = serverDriver.markAsTemplate(server.getInstanceId(), vendor.getUuid(), null);
            if (result.isFailed()) {
                return new BocloudResult<>(false, "模板转换失败");
            }
            server.setIsTemplate(true);
            cloudServerRepository.update(server);
            Image image = new Image(server.getName(), null, null, server.getDisk().doubleValue(), null, "ACTIVE", null);
            image.setTemplateId(server.getId());
            image.setVendorType(vendor.getType());
            image.setImageUuid(server.getInstanceId());
            image.preSave(context.getTarget(), context.getTarget(), vendor.getId(), 0L, context.getProject());
            image.setCatalog("VM");
            image.setOsCategory(server.getOsCategory());
            image.setOsName(server.getOsName());
            imageRepository.save(image);
            resourceRepository.remove(id, ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
                context.getTarget());
            return new BocloudResult<>(true, "模板转换成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "模板转换失败");
        }
    }

    @Override
    public BocloudResult vcChangePasswd(VmModifyParam vmModifyParam, RequestContext context) {
        JSONObject object = JSONObject.parseObject(JSON.toJSONString(vmModifyParam));
        try {
            Optional.ofNullable(object).orElseThrow(() -> new Exception("参数格式错误"));
            Encryptor encryptor = new AESEncrptor();
            String oldPass = object.getString("oldPasswd");
            if (!StringUtils.isEmpty(oldPass)) {
                oldPass = encryptor.decrypt(oldPass.trim(), null);
            }
            String newPass = object.getString("newPasswd");
            if (!StringUtils.isEmpty(newPass)) {
                newPass = encryptor.decrypt(newPass.trim(), null);
            }
            Encryptor encryptorDes = new DESEncrptor();
            String newPassDes = encryptorDes.encrypt(newPass, "BocloudCMP");
            CloudServer server = cloudServerRepository.query(object.getLong("id"));
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            final String oldPasswd = oldPass;
            final String newPasswd = newPass;
            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".vm";
                String content = "密码修改成功";
                try {
                    BocloudResult result = serverDriver.changeVspVmPasswd(server.getInstanceId(), oldPasswd, newPasswd,
                        vendor.getUuid(), server.getRegionId());
                    if (result.isSuccess()) {
                        ServerModel model =
                            JSONObject.parseObject(JSONObject.toJSONString(result.getData()), ServerModel.class);
                        if (model != null && !"".equals(model) && null != model.getAccount()) {
                            server.setAccount(model.getAccount());
                        }
                        server.setPswd(newPasswd);
                        server.setGmtModify(new Date());
                        cloudServerRepository.update(server);
                    } else {
                        content = result.getMessage();
                    }
                    ResourceEvent event =
                        new ResourceEvent(server.getId(), "修改密码", result.isSuccess() ? "密码修改成功" : "密码修改失败",
                            context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                    resourceEventRepository.save(event);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                        MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                    // 向堡垒机发送修改密码消息
                    if (server.getVendorType().equals(CloudProvider.VMWARE.name())) {
                        sendUpdateMsgToShterm(newPassDes, server);
                    }
                } catch (Exception e) {
                    logger.error("虚拟机修改密码失败 ： " + e.getMessage());
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                        MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                }
            }).start();
            return new BocloudResult<>(true, "修改密码任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("Get error message:", e);
            return new BocloudResult<>(false, "虚拟机修改密码失败");
        }
    }

    /**
     * @param newPassDes
     * @param server
     * @return void
     * @Author: lxy
     * @Description: 向堡垒机发送修改密码消息
     * @Date 2021/5/16 19:32
     * @throws:
     **/
    private void sendUpdateMsgToShterm(String newPassDes, CloudServer server) {
        List<String> ips = new ArrayList<>();
        if (null != server.getPrivateIps()) {
            getIps(server.getPrivateIps(), ips);
            String username = server.getOsCategory().equalsIgnoreCase("LINUX") ? "root" : "administrator";
            for (String ip : ips) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("name", server.getName());
                jsonObject.put("oldName", server.getName());
                jsonObject.put("privateIps", ip);
                jsonObject.put("password", newPassDes);
                jsonObject.put("username", username);
                amqpTemplate.convertAndSend("update.shterm.queue", jsonObject);
                logger.info("send rabbitmq topic is : {} success ，message is ：{}", "update.shterm.queue",
                    jsonObject.toJSONString());
            }
        }
    }

    private void getIps(String privateIps, List<String> ips) {
        List<JSONObject> privateIpsList = JSONArray.parseArray(privateIps, JSONObject.class);
        if (ListTool.isEmpty(privateIpsList)) {
            return;
        }
        for (JSONObject json : privateIpsList) {
            String address = json.getString("address");
            if (StringUtils.isEmpty(address)) {
                continue;
            }
            ips.add(address);
        }
    }

    @Override
    public BocloudResult batchModifyLabel(BatchModifyLabelParam params, RequestContext context) {
        try {
            List<Long> serverIds = params.getServerIds();
            List<JSONObject> resourceLabels = params.getResourceLabels();
            if (ListTool.isEmpty(serverIds)) {
                return new BocloudResult<>(false, "没有需要配置标签的虚拟机");
            }
            List<Long> labelIds = new ArrayList<>();
            if (!ListTool.isEmpty(resourceLabels)) {
                for (JSONObject label : resourceLabels) {
                    String key = label.getString("key");
                    String value = label.getString("value");
                    Label existsLabel = labelRepository.getLabel(key, value, "VM");
                    if (null != existsLabel) {
                        labelIds.add(existsLabel.getId());
                        continue;
                    }
                    Label newLabel = new Label(key, value, "VM");
                    labelService.create(newLabel);
                    labelIds.add(newLabel.getId());
                }
            }
            for (Long serverId : serverIds) {
                CloudServer server = cloudServerRepository.query(serverId);
                if (null == server) {
                    continue;
                }
                server.setResourceLabel(JSONObject.toJSONString(resourceLabels));
                server.setGmtModify(new Date());
                cloudServerRepository.update(server);
                // 保存虚机 标签关联关系
                serverLabelRepository.deleteByTarget(serverId, "VM");
                for (Long labelId : labelIds) {
                    serverLabelRepository.save(new ServerLabel(serverId, labelId, "VM", server.getVendorId()));
                }

            }
            return new BocloudResult<>(true, "标签配置成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "标签配置失败");
        }
    }

    @Override
    public BocloudResult performance(ServerPerformanceParam params) {
        try {
            CloudVendor vendor = this.cloudVendorRepository.query(params.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            List<String> types = Lists.newArrayList();
            types.add("CPU");
            types.add("DISK");
            types.add("POWER");
            types.add("MEM");
            types.add("NET");
            types.add("SYSTEM");
            return new VmwareMonitorUtils(monitorDriver).getPerformance(JSON.parseObject(JSON.toJSONString(params)),
                vendor.getUuid(), types, "VirtualMachine");
        } catch (Exception e) {
            logger.error("查询数据失败", e);
            return new BocloudResult<>(false, "查询失败");
        }

    }

    @Override
    public BocloudResult diskExtend(String params, RequestContext context) {
        JSONObject jsonObject = JSONObject.parseObject(params);
        if (null == jsonObject) {
            return new BocloudResult<>(false, "参数格式错误");
        }
        Long id = jsonObject.getLong("id");
        Long volumeId = jsonObject.getLong("volumeId");
        Integer extendSize = jsonObject.getInteger("extendSize");
        String path = CloudServer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudServer server = cloudServerRepository.get(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            Volume disk = volumeRepository.query(volumeId);
            Optional.ofNullable(disk).orElseThrow(() -> new Exception("虚拟机磁盘设备不存在"));
            BocloudResult result =
                serverDriver.diskExtend(server.getInstanceId(), disk.getName(), extendSize, vendor.getUuid(), null);
            if (result.isFailed()) {
                return result;
            }
            List<Volume> volumes = volumeRepository.listByServerId(id);
            if (!ListTool.isEmpty(volumes)) {
                for (Volume volume : volumes) {
                    if (disk.getName().equals(volume.getName())) {
                        volume.setSize(volume.getSize() + extendSize);
                        volume.setGmtModify(new Date());
                        volumeRepository.update(volume);
                        break;
                    }
                }
            }
            Integer oldDiskSize = server.getDisk();
            if (null == oldDiskSize) {
                oldDiskSize = 0;
            }
            server.setDisk(oldDiskSize + extendSize);
            server.setGmtModify(new Date());
            cloudServerRepository.update(server);
            return new BocloudResult<>(true, "虚拟机磁盘扩容成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "虚拟机磁盘扩容失败");
        }
    }

    @Override
    public BocloudResult vmrcConsole(Long id) {
        try {
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            return serverDriver.vmrcConsole(server.getInstanceId(), vendor.getUuid(), null);
        } catch (Exception e) {
            logger.info("query vmrc url error:", e);
            return new BocloudResult<>(false, "获取到控制台URL失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult vmToolsInstall(String params, RequestContext context) {
        JSONObject object = JSONObject.parseObject(params);
        try {
            Optional.ofNullable(object).orElseThrow(() -> new Exception("参数格式错误"));
            Long id = object.getLong("id");
            String ip = object.getString("ip");
            String account = object.getString("account");
            String password = object.getString("password");
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            // 操作系统名称
            if (StringUtils.isEmpty(server.getOsName())) {
                return new BocloudResult<>(false, "当前虚拟机操作系统不明，安装失败");
            }
            String osCategory = server.getOsName().contains("Windows") ? "Windows" : "Linux";
            Map<String, Object> paramMap = Maps.newHashMap();
            List<Map<String, Object>> targets = Lists.newArrayList();
            Map<String, Object> target = Maps.newHashMap();
            target.put("category", osCategory);
            target.put("pasd", password);
            target.put("host", ip);
            target.put("user", account);
            Integer port = 22;
            if (!"Linux".equalsIgnoreCase(osCategory)) {
                port = 5986;
            } else {
                target.put("sudo", true);
            }
            target.put("port", port);
            targets.add(target);
            paramMap.put("targets", targets);
            return vmToolsInstallService.install(vendor, server, paramMap, context);
        } catch (Exception e) {
            logger.info("vmware tools install fail:", e);
            return new BocloudResult<>(false, "Vmware Tools安装失败:" + e.getMessage());
        }
    }

    /**
     * 重装系统
     */
    @Override
    public BocloudResult resetInstance(String params, RequestContext context) {
        try {
            JSONObject parseObject = JSON.parseObject(params);
            Optional.ofNullable(parseObject).orElseThrow(() -> new Exception("参数格式错误"));
            String password = parseObject.getString("password");
            String keypairId = parseObject.getString("keypairId");
            CloudServer server = cloudServerRepository.query(parseObject.getLong("id"));
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            Image image = null;
            if (CloudProvider.TIANYI.name().equalsIgnoreCase(vendor.getType())) {
                image = imageRepository.queryByImageUuid(parseObject.getString("imageUuid"));
                Optional.ofNullable(image).orElseThrow(() -> new Exception("镜像不存在"));
            } else if (CloudProvider.QCLOUD.name().equalsIgnoreCase(vendor.getType())
                || CloudProvider.PQCLOUD.name().equalsIgnoreCase(vendor.getType())) {
            } else {
                image = imageRepository.query(parseObject.getLong("imageId"));
                Optional.ofNullable(image).orElseThrow(() -> new Exception("镜像不存在"));
            }
            String serverStatus = server.getStatus();
            server.setStatus(BocloudStatus.Server.SYSTEMRESIZING.name());
            cloudServerRepository.update(server);
            Image finalImage = image;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String content = "重装系统失败！";
                    String operate = vendor.getType().toLowerCase() + ".vm";
                    try {
                        ServerModel model = new ServerModel();
                        model.setRegionId(server.getRegionId());
                        model.setInstanceId(server.getInstanceId());
                        if (null != finalImage) {
                            model.setImageUuid(finalImage.getImageUuid());
                        }
                        if (!StringUtils.isEmpty(password)) {
                            model.setPassword(new AESEncrptor().decrypt(password.trim(), null));
                        }
                        model.setKeypairName(keypairId);
                        BocloudResult result =
                            serverDriver.resetInstance(model, vendor.getUuid(), server.getRegionId());
                        if (result.isSuccess()) {
                            ServerModel serverModel =
                                JSON.parseObject(JSON.toJSONString(result.getData()), ServerModel.class);
                            serverKeyPairRepository.removeBySid(server.getId());
                            if (CloudProvider.QCLOUD.name().equalsIgnoreCase(vendor.getType())
                                || CloudProvider.PQCLOUD.name().equalsIgnoreCase(vendor.getType())) {
                                server.setPassword("");
                                if (null != keypairId) {
                                    Keypair keypair = keyPairRepository.getByFingerprint(keypairId, vendor.getId());
                                    if (null != keypair) {
                                        ServerKeypair serverKeypair = new ServerKeypair();
                                        serverKeypair.setKeypairId(keypair.getId());
                                        serverKeypair.setServerId(server.getId());
                                        serverKeyPairRepository.save(serverKeypair);
                                    }
                                } else {
                                    if (null != password && !"".equalsIgnoreCase(password)) {
                                        server.setPassword(password);
                                    }
                                }
                                content = "系统重置成功！";
                            } else {
                                String imageUuid = finalImage.getImageUuid();
                                server.setOsVersion(serverModel.getOsVersion());
                                server.setOsName(serverModel.getOsName());
                                if (!StringUtils.isEmpty(serverModel.getOsCategory())) {
                                    server.setOsCategory(serverModel.getOsCategory());
                                }
                                server.setImageUuid(imageUuid);
                                server.setPswd(password);
                                content = "重装系统成功！";
                            }
                            server.setStatus(serverModel.getStatus());
                            server.setGmtModify(new Date());
                            cloudServerRepository.update(server);
                        } else {
                            content = result.getMessage();
                            server.setStatus(serverStatus);
                            cloudServerRepository.update(server);
                        }
                        ResourceEvent event =
                            new ResourceEvent(server.getId(), "重装系统", result.isSuccess() ? "成功" : "失败",
                                context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                        resourceEventRepository.save(event);
                        resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                            MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                    } catch (Exception e) {
                        logger.error("重装系统失败", e);
                        resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                    }
                }
            }).start();
            return new BocloudResult<>(true, "重装系统任务已下发，正在执行...");
        } catch (Exception e) {
            logger.info("重装系统失败:", e);
            return new BocloudResult<>(false, e.getMessage());
        }
    }

    /**
     * 调整宽带上限
     */
    @Override
    public BocloudResult setMaxBandwidth(VmGenericParam vmGenericParam, RequestContext context) {
        try {
            Optional.ofNullable(vmGenericParam).orElseThrow(() -> new Exception("参数格式错误"));
            Integer internetMaxBandwidthOut = vmGenericParam.getInternetMaxBandwidthOut();
            CloudServer server = cloudServerRepository.query(vmGenericParam.getId());
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            BocloudResult result = serverDriver.resetInternetMaxBandwidthOut(server.getInstanceId(),
                internetMaxBandwidthOut, vendor.getUuid(), server.getRegionId());
            if (result.isSuccess()) {
                server.setInternetMaxBandwidthOut(internetMaxBandwidthOut);
                cloudServerRepository.update(server);
                return new BocloudResult<>(true, "修改成功");
            }
            return new BocloudResult<>(false, result.getMessage());
        } catch (Exception e) {
            logger.info("修改宽带失败:", e);
            return new BocloudResult<>(false, "修改宽带失败:" + e.getMessage());
        }
    }

    /**
     * 查询当前虚拟机绑定密钥列表
     */
	@Override
	public BocloudResult<List<Keypair>> listunBindKeyPair(Long id, RequestContext context) {
		try {
			CloudServer server = cloudServerRepository.query(id);
			Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
			CloudVendor cloudVendor = cloudVendorRepository.query(server.getVendorId());
			Optional.ofNullable(cloudVendor).orElseThrow(() -> new Exception("云平台不存在"));
			String region = null;
			Long tenantId = context.getTenant();
			if (CloudProvider.QCLOUD.name().equalsIgnoreCase(cloudVendor.getType())) {
				region = server.getRegionId();
			}
			List<Keypair> keyPairList = keyPairRepository.listunBindKeyPair(server.getId(), server.getVendorId(),
					tenantId, region);
			return new BocloudResult<>(true, keyPairList, "查询成功");
		} catch (Exception e) {
			logger.info("查询失败:", e);
			return new BocloudResult<>(false, e.getMessage());
		}
	}

    /**
     * 查询当前虚拟机绑定密钥列表
     *
     * @param id
     * @return
     */
    @Override
    public BocloudResult<List<Keypair>> listBindedKeyPair(Long id) {
        try {
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            List<Keypair> keyPairList = keyPairRepository.listByInstanceId(server.getId());
            return new BocloudResult<>(true, keyPairList, "查询成功");
        } catch (Exception e) {
            logger.info("查询失败:", e);
            return new BocloudResult<>(false, e.getMessage());
        }
    }

    /**
     * 绑定密钥
     */
    @Override
    public BocloudResult bindKeypair(KeypairParam keypairParam, RequestContext context) {
        try {
            if (null == keypairParam) {
                return new BocloudResult<>(false, "参数格式异常");
            }
            CloudServer server = cloudServerRepository.query(keypairParam.getId());
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            if (!CloudProvider.QCLOUD.name().equals(vendor.getType())
                && !CloudProvider.PQCLOUD.name().equals(vendor.getType())) {
                if ("RUNNING".equalsIgnoreCase(server.getStatus())) {
                    return new BocloudResult<>(false, "绑定密钥需要在关机状态下操作!");
                }
            }
            Keypair keypair = keyPairRepository.query(keypairParam.getKeypairId());
            Optional.ofNullable(keypair).orElseThrow(() -> new Exception("密钥不存在"));
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String content = "绑定失败！！";
                    String operate = vendor.getType().toLowerCase() + ".vm";
                    try {
                        ServerModel serverModel = new ServerModel();
                        serverModel.setInstanceIds(new String[] {server.getInstanceId()});
                        serverModel.setKeypairIds(new String[] {keypair.getFingerprint()});
                        BocloudResult bocloudResult =
                            serverDriver.bindKeypair(serverModel, vendor.getUuid(), server.getRegionId());
                        if (bocloudResult.isSuccess()) {
                            ServerKeypair serverKeypair = new ServerKeypair();
                            serverKeypair.setKeypairId(keypair.getId());
                            serverKeypair.setServerId(server.getId());
                            serverKeyPairRepository.save(serverKeypair);
                            content = "虚拟机" + server.getName() + "绑定密钥" + keypair.getFingerprint() + "成功";
                        } else {
                            content = bocloudResult.getMessage();
                        }
                        ResourceEvent event =
                            new ResourceEvent(server.getId(), "密钥绑定", bocloudResult.isSuccess() ? "成功" : "失败",
                                context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                        resourceEventRepository.save(event);
                        resourceEventPublisher.send(new OperateResult(bocloudResult.isSuccess(), content, operate,
                            MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                    } catch (Exception e) {
                        logger.error("虚拟机绑定密钥失败 ： ", e);
                        resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                    }
                }
            }).start();
            return new BocloudResult<>(true, "绑定密钥任务已下发，正在执行...");
        } catch (Exception e) {
            logger.info("绑定密钥失败:", e);
            return new BocloudResult<>(false, e.getMessage());
        }
    }

    /**
     * 解绑密钥
     */
    @Override
    public BocloudResult unbindKeypair(KeypairParam keypairParam, RequestContext context) {
        try {
            if (null == keypairParam) {
                return new BocloudResult<>(false, "参数格式异常");
            }
            CloudServer server = cloudServerRepository.query(keypairParam.getId());
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            if (!CloudProvider.QCLOUD.name().equals(vendor.getType())
                && !CloudProvider.PQCLOUD.name().equals(vendor.getType())) {
                if ("RUNNING".equalsIgnoreCase(server.getStatus())) {
                    return new BocloudResult<>(false, "绑定密钥需要在关机状态下操作!");
                }
            }
            Keypair keypair = keyPairRepository.query(keypairParam.getKeypairId());
            Optional.ofNullable(keypair).orElseThrow(() -> new Exception("密钥不存在"));
            new Thread(() -> {
                String content = "解绑成功";
                String operate = vendor.getType().toLowerCase() + ".vm";
                try {
                    ServerModel serverModel = new ServerModel();
                    serverModel.setInstanceIds(new String[] {server.getInstanceId()});
                    serverModel.setKeypairIds(new String[] {keypair.getFingerprint()});
                    BocloudResult result =
                        serverDriver.unbindKeypair(serverModel, vendor.getUuid(), server.getRegionId());
                    if (result.isSuccess()) {
                        serverKeyPairRepository.remove(keypair.getId(), server.getId());
                    } else {
                        content = result.getMessage();
                    }
                    ResourceEvent event = new ResourceEvent(server.getId(), "密钥解绑", result.isSuccess() ? "成功" : "失败",
                        context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                    resourceEventRepository.save(event);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                        MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("虚拟机绑定密钥失败 ： ", e);
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                        MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                }
            }).start();
            return new BocloudResult<>(true, "解绑密钥任务已下发，正在执行...");
        } catch (Exception e) {
            logger.info("解绑密钥失败:", e);
            return new BocloudResult<>(false, e.getMessage());
        }
    }

    @Override
    public BocloudResult listByPoolGroupId(Integer page, Integer rows, String params, RequestContext context) {
        GridBean gridBean = null;
        try {
            JSONObject object = JSON.parseObject(params, JSONObject.class);
            Optional.ofNullable(object).orElseThrow(() -> new Exception("参数格式错误"));
            List<Param> param = Lists.newArrayList();
            Long poolGroupId = object.getLong("poolGroupId");
            PoolGroup poolGroup = poolGroupRepository.query(poolGroupId);
            Optional.ofNullable(poolGroup).orElseThrow(() -> new Exception("资源池不存在"));
            Long vendorId = poolGroup.getVendorId();
            CloudVendor cloudVendor = cloudVendorRepository.query(vendorId);
            String category = object.getString("category");
            List<PoolGroupRelation> list = poolGroupRelationRepository.list(poolGroupId, category);
            param.add(new Param(MapTools.simpleMap(Common.VENDORID, poolGroup.getVendorId()), Sign.EQ));
            String name = object.getString("name");
            if (null != name && !"".equals(name)) {
                param.add(new Param(MapTools.simpleMap("name", name), Sign.LK));
            }
            String status = object.getString("status");
            if (null != status && !"".equals(status)) {
                param.add(new Param(MapTools.simpleMap("status", status), Sign.EQ));
            }
            if (PoolGroupTarget.Region.name().equals(category)) {
                List<String> regionList = new ArrayList<>();
                regionList.add(poolGroup.getRegion());
                if (CloudProvider.OPENSTACK.name().equals(cloudVendor.getType())) {
                    param.add(new Param(MapTools.simpleMap("region", this.generateRegions(regionList)), Sign.IN));
                } else {
                    param.add(new Param(MapTools.simpleMap("regionId", this.generateRegions(regionList)), Sign.IN));
                }
            } else if (PoolGroupTarget.Vdc.name().equals(category)) {
                List<Long> vdcIds = new ArrayList<>();
                for (PoolGroupRelation poolGroupRelation : list) {
                    vdcIds.add(poolGroupRelation.getTarget());
                }
                param.add(new Param(MapTools.simpleMap("vdcId", this.generateHosts(vdcIds)), Sign.IN));
            } else if (PoolGroupTarget.Host.name().equals(category)) {
                List<Long> hostIds = new ArrayList<>();
                for (PoolGroupRelation poolGroupRelation : list) {
                    hostIds.add(poolGroupRelation.getTarget());
                }
                param.add(new Param(MapTools.simpleMap("hostId", this.generateHosts(hostIds)), Sign.IN));
            } else if (PoolGroupTarget.Cluster.name().equals(category)) {
                List<Long> hostIds = new ArrayList<>();
                for (PoolGroupRelation poolGroupRelation : list) {
                    Long target = poolGroupRelation.getTarget();
                    List<Server> listByCluster = serverRepository.listByCluster(target);
                    for (Server server : listByCluster) {
                        hostIds.add(server.getId());
                    }
                }
                param.add(new Param(MapTools.simpleMap("hostId", this.generateHosts(hostIds)), Sign.IN));
            } else {
                return new BocloudResult<>(false, "资源不存在");
            }
            Map<String, String> sorter = Maps.newHashMap();
            sorter.put("gmtCreate", Common.ONE);
            int total = this.cloudServerRepository.count(param);
            List<CloudServer> serverList = this.cloudServerRepository.list(page, rows, param, sorter);
            gridBean = GridHelper.getBean(page, rows, total, serverList);
            gridBean.setRows(serverList);
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("Query vm list fail:", e);
            return new BocloudResult<>(false, "查询失败", null, null);
        }
    }

    private Object generateHosts(List<Long> hostIds) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < hostIds.size(); i++) {
            builder.append(hostIds.get(i)).append(",");
        }
        builder.append(" -1 ");
        return builder.toString();
    }

    private String generateRegions(List<String> regList) {
        StringBuilder builder = new StringBuilder();
        if (null != regList && regList.size() > 0) {
            for (int i = 0; i < regList.size(); i++) {
                builder.append("'").append(regList.get(i)).append("'").append(",");
            }
        }
        builder.append(" '-1' ");
        return builder.toString();
    }

    @Override
    public BocloudResult createDisk(String params, RequestContext context, String queue) {
        JSONObject object = JSONTools.isJSONObj(params);
        Integer size = object.getInteger("size");
        Long serverId = object.getLong("serverId");
        try {
            CloudServer server = cloudServerRepository.query(serverId);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudServerBean bean = new CloudServerBean();
            bean.setId(serverId);
            bean.setName(server.getName());
            bean.setExtendDisk(size);
            bean.setCpu(server.getCpu());
            bean.setMemory(server.getMemory());
            List<DataStore> stores = this.dataStoreRepository.listByHost(server.getHostId());
            for (DataStore store : stores) {
                if (store.getFreeSpace() > size) {
                    bean.setDatastore(store.getName());
                    break;
                }
            }
            if (StringUtils.isEmpty(bean.getDatastore())) {
                return new BocloudResult<>(false, "虚拟机所在主机的数据存储空间不足");
            }
            return cloudServerService.modify(bean, context, queue);
        } catch (Exception e) {
            logger.error("create server disk error:", e);
            return new BocloudResult<>(false, "创建失败");
        }
    }

    @Override
    public BocloudResult<List<Volume>> listVolume(String params) {
        try {
            JSONObject jsonObject = JSONTools.isJSONObj(params);
            Optional.ofNullable(jsonObject).orElseThrow(() -> new Exception("参数异常"));
            // 虚拟机ID
            Long cloudServerId = jsonObject.getLong("id");
            CloudServer cloudServer = cloudServerRepository.query(cloudServerId);
            Optional.ofNullable(cloudServer).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(cloudServer.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            List<Volume> volumes = null;
            if (CloudProvider.POWERVC.name().equals(vendor.getType())) {
                volumes = volumeRepository.listVolumeByServerId(cloudServerId);
            } else {
                volumes = volumeRepository.listByServerId(cloudServerId);
            }
            return new BocloudResult<>(true, volumes, "查询成功");
        } catch (Exception e) {
            logger.error("listVolume failed:", e);
            return new BocloudResult<>(false, "查询失败", null, null);
        }
    }

    @Override
    public BocloudResult attachVolume(Long serverId, Volume volume, RequestContext context) {
        try {
            CloudServer cloudServer = cloudServerRepository.query(serverId);
            Optional.ofNullable(cloudServer).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor cloudVendor = cloudVendorRepository.query(cloudServer.getVendorId());
            Optional.ofNullable(cloudVendor).orElseThrow(() -> new Exception("云平台不存在"));
            VolumeModel volumeModel = new VolumeModel();
            volumeModel.setBootVolume(volume.getBootVolume());
            if (volume.getId() == null) {
                // // 创建一个卷
                volumeModel.setName(volume.getName());
                volumeModel.setSize(volume.getSize());
                volumeModel.setRemark(volume.getRemark());
                volumeModel.setMultiattach(volume.getMultiattach());
            }
            new Thread(() -> {
                OperateResult result = new OperateResult(true, "", "powervc.vm",
                    MapTools.simpleMap(Common.VENDORID, cloudVendor.getId()), OperateCategory.ResourceEvent, context);
                try {
                    if (volumeModel.getVolumeUuid() == null) {
                        BocloudResult bocloudResult = volumeDriver.create(cloudVendor.getUuid(), null, volumeModel);
                        if (bocloudResult.isFailed()) {
                            result.setSuccess(false);
                            result.setMessage("创建卷[" + volumeModel.getName() + "]失败：" + bocloudResult.getMessage());
                            resourceEventPublisher.send(result);
                            return;
                        }
                        volumeModel.setVolumeUuid(((VolumeModel)bocloudResult.getData()).getVolumeUuid());
                    }
                    BocloudResult bocloudResult = serverDriver.attachVolume(cloudVendor.getUuid(), null,
                        cloudServer.getInstanceId(), volumeModel);
                    if (bocloudResult.isFailed()) {
                        result.setSuccess(false);
                        result.setMessage("虚拟机[" + cloudServer.getName() + "]附加卷[" + volumeModel.getName() + "]失败："
                            + bocloudResult.getMessage());
                        resourceEventPublisher.send(result);
                        return;
                    }
                    bocloudResult = volumeDriver.detail(volumeModel.getVolumeUuid(), cloudVendor.getUuid(), null);
                    if (bocloudResult.isFailed()) {
                        result.setSuccess(false);
                        result.setMessage("获取卷[" + volumeModel.getName() + "]失败：" + bocloudResult.getMessage());
                        resourceEventPublisher.send(result);
                        return;
                    }
                    // 返回异步消息
                    result.setSuccess(true);
                    result.setMessage("虚拟机[" + cloudServer.getName() + "]附加卷[" + volumeModel.getName() + "]成功");
                    resourceEventPublisher.send(result);
                } catch (Exception e) {
                    logger.error("虚拟机[" + cloudServer.getName() + "]附加卷[" + volumeModel.getName() + "]失败", e);
                    result.setSuccess(false);
                    result.setMessage(
                        "虚拟机[" + cloudServer.getName() + "]附加卷[" + volumeModel.getName() + "]失败：" + e.getMessage());
                    resourceEventPublisher.send(result);
                } finally {
                    try {
                        // 更新任务状态
                        CloudServer server = cloudServerRepository.query(serverId);
                        JSONObject props = StringUtils.isEmpty(server.getProps()) ? new JSONObject()
                            : JSON.parseObject(server.getProps());
                        props.remove("taskStatus");
                        server.setProps(props.toJSONString());
                        cloudServerRepository.update(server);
                    } catch (Exception e) {
                        logger.error("虚拟机[" + cloudServer.getName() + "]附加卷[" + volumeModel.getName() + "]失败", e);
                    }
                }
            }).start();
            // 更改虚拟机的任务状态，一定要放在最后
            JSONObject props = StringUtils.isEmpty(cloudServer.getProps()) ? new JSONObject()
                : JSON.parseObject(cloudServer.getProps());
            props.put("taskStatus", "attaching_volume");
            cloudServer.setProps(props.toJSONString());
            cloudServerRepository.update(cloudServer);
            return new BocloudResult<>(true, "任务已经下发，正在执行...");
        } catch (Exception e) {
            logger.error("附加卷失败：", e);
            return new BocloudResult<>(false, "附加卷失败：" + e.getMessage());
        }
    }

    @Override
    public BocloudResult detachVolume(Long serverId, long volumeId, RequestContext context) {
        try {
            CloudServer cloudServer = cloudServerRepository.query(serverId);
            Optional.ofNullable(cloudServer).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor cloudVendor = cloudVendorRepository.query(cloudServer.getVendorId());
            Optional.ofNullable(cloudVendor).orElseThrow(() -> new Exception("云平台不存在"));
            Volume volume = volumeRepository.query(volumeId);
            Optional.ofNullable(volume).orElseThrow(() -> new Exception("存储卷不存在"));
            new Thread(() -> {
                OperateResult result = new OperateResult(true, "", "powervc.vm",
                    MapTools.simpleMap(Common.VENDORID, cloudVendor.getId()), OperateCategory.ResourceEvent, context);
                try {
                    VolumeModel volumeModel = new VolumeModel();
                    volumeModel.setVolumeUuid(volume.getVolumeUuid());
                    BocloudResult bocloudResult = serverDriver.detachVolume(cloudVendor.getUuid(), null,
                        cloudServer.getInstanceId(), volumeModel);
                    if (bocloudResult.isFailed()) {
                        result.setSuccess(false);
                        result.setMessage("虚拟机[" + cloudServer.getName() + "]拆离卷[" + volume.getName() + "]失败："
                            + bocloudResult.getMessage());
                        resourceEventPublisher.send(result);
                        return;
                    }
                    bocloudResult = volumeDriver.detail(volume.getVolumeUuid(), cloudVendor.getUuid(), null);
                    if (bocloudResult.isFailed()) {
                        result.setSuccess(false);
                        result.setMessage("获取卷[" + volume.getName() + "]失败：" + bocloudResult.getMessage());
                        resourceEventPublisher.send(result);
                        return;
                    }
                    result.setMessage("虚拟机[" + cloudServer.getName() + "]拆离卷[" + volume.getName() + "]成功");
                } catch (Exception e) {
                    logger.error("虚拟机[" + cloudServer.getName() + "]拆离卷[" + volume.getName() + "]失败", e);
                    result.setSuccess(false);
                    result.setMessage(
                        "虚拟机[" + cloudServer.getName() + "]拆离卷[" + volume.getName() + "]失败：" + e.getMessage());
                }
                resourceEventPublisher.send(result);
            }).start();
            return new BocloudResult<>(true, "任务已经下发，正在执行...");
        } catch (Exception e) {
            logger.error("拆离卷失败：", e);
            return new BocloudResult<>(false, "拆离卷失败：" + e.getMessage());
        }
    }

    @Override
    public BocloudResult beforeCaptureImage(String params, RequestContext context) {
        try {
            JSONObject object = JSONTools.isJSONObj(params);
            Optional.ofNullable(object).orElseThrow(() -> new Exception("参数格式错误"));
            // 虚拟机ID
            long serverId = object.getLongValue(Common.ID);
            CloudServer server = cloudServerRepository.query(serverId);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            // 云供应商
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            List<Volume> paramVolumes = object.getJSONArray("volumes").toJavaList(Volume.class);
            paramVolumes.sort((o1, o2) -> o2.getBootVolume().compareTo(o1.getBootVolume()));
            int bootVolumeCount = 0;
            List<VolumeModel> driverVolumes = new ArrayList<>();
            for (Volume paramVolume : paramVolumes) {
                if (paramVolume.getBootVolume()) {
                    bootVolumeCount++;
                }
                Volume dbVolume = volumeRepository.query(paramVolume.getId());
                if (dbVolume == null) {
                    return new BocloudResult<>(false, "未找到卷Id：" + paramVolume.getId());
                }
                VolumeModel driverVolume = new VolumeModel();
                driverVolume.setVolumeUuid(dbVolume.getVolumeUuid());
                driverVolume.setBootVolume(paramVolume.getBootVolume());
                driverVolumes.add(driverVolume);
            }
            if (bootVolumeCount < 1) {
                return new BocloudResult<>(false, "至少一个卷必须位于引导集中");
            }
            ImageModel imageModel = new ImageModel();
            imageModel.setDiskDeviceMappings(driverVolumes);
            imageModel.setOsName(object.getString("osName"));
            BocloudResult bocloudResult =
                serverDriver.beforeCaptureImage(vendor.getUuid(), server.getInstanceId(), imageModel, null);
            if (bocloudResult.isFailed()) {
                return new BocloudResult<>(false, bocloudResult.getMessage());
            }
            for (Volume paramVolume : paramVolumes) {
                Volume getVolume = volumeRepository.query(paramVolume.getId());
                getVolume.setBootVolume(paramVolume.getBootVolume());
                volumeRepository.update(getVolume);
            }
        } catch (Exception e) {
            logger.error("CloudServer before captureImage error:", e);
            return new BocloudResult<>(false, "捕获映像前的确认其详细信息失败");
        }
        return new BocloudResult<>(true, "捕获映像前的确认其详细信息成功");
    }

    @Override
    public BocloudResult captureImage(String params, RequestContext context) {
        JSONObject object = JSONTools.isJSONObj(params);
        if (null == object) {
            return new BocloudResult<>(false, "参数格式错误");
        }
        long serverId = object.getLongValue(Common.ID);
        String path = CloudServer.class.getSimpleName() + "_" + serverId;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            // 虚拟机ID
            CloudServer server = cloudServerRepository.query(serverId);
            if (null == server) {
                logger.error("get cloudServer failure!");
                return new BocloudResult<>(false, "虚拟机不存在!");
            }
            // 云供应商
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            if (null == vendor) {
                logger.error("get cloudVendor failure!");
                return new BocloudResult<>(false, "云平台不存在!");
            }
            // 捕获映像的名称
            String imageName = object.getString("name");
            // 数据卷uuid列表
            JSONArray volumeUuids = object.getJSONArray("volumes");
            List<Volume> volumes = volumeRepository.listVolumeByServerId(serverId);
            for (Volume volume : volumes) {
                if (volume.getBootVolume() && !volumeUuids.contains(volume.getVolumeUuid())) {
                    volumeUuids.add(volume.getVolumeUuid());
                }
            }
            // 强制关机
            boolean forceStop = object.getBoolean("forceStop") == null ? false : object.getBoolean("forceStop");
            // 记录捕获影响前虚拟机的状态
            String oldStatus = server.getStatus();
            // powervc不允许在开机的状态下捕获映像
            if (!BocloudStatus.Server.RUNNING.name().equals(server.getStatus())
                & !BocloudStatus.Server.STOPPED.name().equals(server.getStatus())) {
                return new BocloudResult<>(false, "虚拟机在" + server.getStatus() + "状态下无法进行捕获操作！");
            }
            if (!forceStop && BocloudStatus.Server.RUNNING.name().equals(server.getStatus())) {
                return new BocloudResult<>(false, "捕获映像前请先将该虚拟机关机!");
            }
            if (forceStop && BocloudStatus.Server.RUNNING.name().equals(server.getStatus())) {
                server.setStatus(BocloudStatus.Server.STOPPING.name());
                cloudServerRepository.update(server);
            }

            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                logger.warn("Get BocloudLock time out!");
                return new BocloudResult<>(false, "请求超时");
            }

            new Thread(() -> {
                String operate = vendor.getType().toLowerCase() + ".vm";
                OperateResult message = new OperateResult(false, "虚拟机" + server.getName() + "捕获映像失败", operate,
                    MapTools.simpleMap(Common.VENDORID, vendor.getId()), OperateCategory.ResourceEvent, context);
                try {
                    // powervc不允许捕获开机状态下的虚拟机映像。如果开机状态需要首先关机
                    BocloudResult bocloudResult;
                    if (forceStop && !BocloudStatus.Server.STOPPED.name().equals(server.getStatus())) {
                        bocloudResult = serverDriver.stop(server.getInstanceId(), vendor.getUuid(), null);
                        if (bocloudResult.isFailed()) {
                            server.setStatus(oldStatus);
                            cloudServerRepository.update(server);

                            message.setMessage(message.getMessage() + ":" + bocloudResult.getMessage());
                            resourceEventPublisher.send(message);
                            return;
                        }
                        server.setStatus(BocloudStatus.Server.STOPPED.name());
                        cloudServerRepository.update(server);
                        resourceEventPublisher.send(new OperateResult(true, "虚拟机" + server.getName() + "已关机，即将捕获映像...",
                            operate, MapTools.simpleMap(Common.VENDORID, vendor.getId()), OperateCategory.ResourceEvent,
                            context));
                    }
                    // 执行捕获映像操作
                    bocloudResult = serverDriver.captureImage(server.getInstanceId(), imageName,
                        volumeUuids.toJavaList(String.class), vendor.getUuid(), server.getRegionId());
                    if (bocloudResult.isFailed()) {
                        message.setMessage(message.getMessage() + ":" + bocloudResult.getMessage());
                        resourceEventPublisher.send(message);
                        return;
                    }
                    // 因为powervc允许映像名称相同，我们只能现在只能通过虚拟机uuid和映像的状来确认是那个映像
                    bocloudResult = imageDriver.list(vendor.getUuid(), null);
                    if (bocloudResult.isFailed()) {
                        message.setMessage(message.getMessage() + ":" + bocloudResult.getMessage());
                        resourceEventPublisher.send(message);
                        return;
                    }
                    @SuppressWarnings("unchecked")
                    List<ImageModel> imageModels = (List<ImageModel>)bocloudResult.getData();
                    ImageModel imageModel = null;
                    for (ImageModel model : imageModels) {
                        if (model.getInstanceUuid() != null && model.getInstanceUuid().equals(server.getInstanceId())
                            && "queued".equals(model.getStatus()) && model.getName().equals(imageName)) {
                            powervcTransportor.insertOrUpdate(vendor, model, context.getTarget());
                            imageModel = model;
                            break;
                        }
                    }
                    if (imageModel == null) {
                        message.setMessage(message.getMessage() + ":执行捕获后未找到映像");
                        resourceEventPublisher.send(message);
                        return;
                    }
                    // 检测是否完成
                    long start = System.currentTimeMillis();
                    while (System.currentTimeMillis() - start < 60 * 1000 * 5) {
                        bocloudResult = imageDriver.detail(imageModel.getImageUuid(), vendor.getUuid(), null);
                        imageModel = (ImageModel)bocloudResult.getData();
                        if (bocloudResult.isFailed() || imageModel == null) {
                            message.setMessage(message.getMessage() + ":执行捕获后未找到映像");
                            resourceEventPublisher.send(message);
                            return;
                        }
                        logger.info("镜像{}当前状态为：{}", imageModel.getName(), imageModel.getStatus());
                        if ("active".equals(imageModel.getStatus())) {
                            // 更新这个映像的卷信息
                            List<VolumeModel> volumeModels = imageModel.getDiskDeviceMappings();
                            for (VolumeModel model : volumeModels) {
                                bocloudResult = volumeDriver.detail(model.getVolumeUuid(), vendor.getUuid(), null);
                                if (bocloudResult.isFailed()) {
                                    message.setMessage(message.getMessage() + ":" + bocloudResult.getMessage());
                                    resourceEventPublisher.send(message);
                                    return;
                                }
                                VolumeModel volumeModel = (VolumeModel)bocloudResult.getData();
                                powervcTransportor.insertOrUpdate(vendor, volumeModel, context.getTarget());
                            }
                            // 创建成功，更新映像的数据库信息
                            powervcTransportor.insertOrUpdate(vendor, imageModel, context.getTarget());
                            // 发送异步消息
                            message.setMessage("捕获映像成功");
                            message.setSuccess(true);
                            resourceEventPublisher.send(message);
                            break;
                        }
                        logger.info("正在捕获映像，3秒后将重新检测...");
                        Thread.sleep(3000);
                    }
                } catch (Exception e) {
                    logger.error("CloudServer createImage error:", e);
                    resourceEventPublisher.send(message);
                } finally {
                    try {
                        CloudServer cloudServer = cloudServerRepository.get(serverId);
                        JSONObject props = StringUtils.isEmpty(cloudServer.getProps()) ? new JSONObject()
                            : JSON.parseObject(cloudServer.getProps());
                        props.remove("taskStatus");
                        cloudServer.setProps(props.toJSONString());
                        cloudServerRepository.update(cloudServer);
                    } catch (Exception e) {
                        logger.error("CloudServer createImage error:", e);
                    }
                }
            }).start();
            // 更改虚拟机的任务状态，一定要放在最后
            JSONObject props =
                StringUtils.isEmpty(server.getProps()) ? new JSONObject() : JSON.parseObject(server.getProps());
            props.put("taskStatus", "image_pending_upload");
            server.setProps(props.toJSONString());
            cloudServerRepository.update(server);
            return new BocloudResult<>(true, "捕获映像任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("CloudServer createImage error:", e);
            return new BocloudResult<>(false, "捕获映像失败");
        }
    }

    @Override
    public BocloudResult listServerByKeypair(JSONObject object, RequestContext context) {
        try {
            Long keypairId = object.getLong("keypairId");
            List<CloudServer> cloudServerList = cloudServerRepository.listByKeypair(keypairId);
            return new BocloudResult<>(true, cloudServerList, "查询成功");
        } catch (Exception e) {
            logger.error("根据keypair查询虚拟机列表:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult listByImageUuid(String imageUuid) {
        try {
            List<CloudServer> cloudServerList = cloudServerRepository.listByImageUuid(imageUuid);
            return new BocloudResult<>(true, cloudServerList, "查询成功");
        } catch (Exception e) {
            logger.error("查询失败:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult listByHostId(long hostId) {
        try {
            List<CloudServer> cloudServerList = cloudServerRepository.listByHid(hostId);
            return new BocloudResult<>(true, cloudServerList, "查询成功");
        } catch (Exception e) {
            logger.error("查询失败:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult listByNetworkId(long networkId) {
        try {
            List<CloudServer> cloudServerList = cloudServerRepository.listByNetworkId(networkId);
            for (CloudServer cloudServer : cloudServerList) {
                cloudServer.setPortFixedIps(portFixedIpRepository.listByDeviceUuid(cloudServer.getInstanceId()));
            }
            return new BocloudResult<>(true, cloudServerList, "查询成功");
        } catch (Exception e) {
            logger.error("查询失败:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    /**
     * 挂载vmware tools安装镜像
     *
     * @param id
     * @return
     */
    @Override
    public BocloudResult mountToolsInstaller(Long id) {
        try {
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            BocloudResult result = serverDriver.mountToolsInstaller(server.getInstanceId(), vendor.getUuid(), null);
            if (result.isFailed()) {
                return result;
            }
            return new BocloudResult<>(true, "挂载vmware tools安装镜像成功");
        } catch (Exception e) {
            logger.error("Get error message:", e);
            return new BocloudResult<>(false, "挂载vmware tools安装镜像失败");
        }
    }

    /**
     * vmware tools配置
     *
     * @param object
     * @param userId
     * @return
     */
    @Override
    public BocloudResult vmToolsConfig(JSONObject object, Long userId) {
        Long id = object.getLong("id");
        String path = CloudServer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudServer cloudServer = cloudServerRepository.query(id);
            Optional.ofNullable(cloudServer).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(cloudServer.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            ServerModel model = new ServerModel();
            model.setInstanceId(cloudServer.getInstanceId());
            JSONObject toolsConfObj = JSONObject.parseObject(object.getString("toolsConfig"));
            // 电源控制
            VmwareToolsConfig powerConfig =
                JSONObject.parseObject(toolsConfObj.getString("power"), VmwareToolsConfig.class);
            // VMware tools设置
            VmwareToolsConfig toolsConfig =
                JSONObject.parseObject(toolsConfObj.getString("tools"), VmwareToolsConfig.class);
            if (null != powerConfig) {
                toolsConfig.setPowerOffType(powerConfig.getPowerOffType());
                toolsConfig.setSuspendType(powerConfig.getSuspendType());
                toolsConfig.setResetType(powerConfig.getResetType());
            }
            model.setVmwareToolsConfig(toolsConfig);
            BocloudResult result = serverDriver.vmToolsConfig(model, vendor.getUuid(), null);
            if (result.isFailed()) {
                return result;
            }
            model = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), ServerModel.class);
            cloudServer.setToolsConfig(model.getToolsConfig());
            cloudServer.setGmtModify(new Date());
            boolean flag = cloudServerRepository.update(cloudServer);
            if (flag) {
                // 同步到cmdb
                List<CmdbInfo> infos = Lists.newArrayList();
                infos.add(CmdbInfoConvertor.getInfo(cloudServer, "modify", null));
                cmdbMessagePublisher.send(CmdbInfoConvertor.getModel(BoCloudService.IMS, infos));
                return new BocloudResult<>(true, "VMware tools配置成功!");
            } else {
                return new BocloudResult<>(true, "VMware tools配置失败!");
            }
        } catch (Exception e) {
            logger.error("Get error message:", e);
            return new BocloudResult<>(false, "VMware tools配置失败!");
        }
    }

    @Override
    public BocloudResult queryByUuid(String uuid) {
        try {
            CloudServer cloudServer = cloudServerRepository.queryByUuid(uuid);
            return new BocloudResult<>(true, cloudServer, "查询成功");
        } catch (Exception e) {
            logger.error("Query cloud server by uuid is error", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult resetStatus(Long serverId, RequestContext context) {
        try {
            CloudServer cloudServer = cloudServerRepository.query(serverId);
            if (cloudServer == null) {
                return new BocloudResult<>(false, "未找到虚拟机");
            }
            CloudVendor cloudVendor = cloudVendorRepository.query(cloudServer.getVendorId());
            if (cloudVendor == null) {
                return new BocloudResult<>(false, "未找到平台");
            }
            new Thread(() -> {
                OperateResult result = new OperateResult(true, "", "powervc.vm",
                    MapTools.simpleMap(Common.VENDORID, cloudVendor.getId()), OperateCategory.ResourceEvent, context);
                try {
                    BocloudResult bocloudResult =
                        serverDriver.resetStatus(cloudVendor.getUuid(), null, cloudServer.getInstanceId());
                    if (bocloudResult.isFailed()) {
                        result.setSuccess(false);
                        result.setMessage("虚拟机[" + cloudServer.getName() + "]重置状态失败：" + bocloudResult.getMessage());
                        resourceEventPublisher.send(result);
                        return;
                    }
                    result.setSuccess(true);
                    result.setMessage("虚拟机[" + cloudServer.getName() + "]重置状态成功");
                    resourceEventPublisher.send(result);
                } catch (Exception e) {
                    logger.error("虚拟机[" + cloudServer.getName() + "]重置状态失败", e);
                    result.setSuccess(false);
                    result.setMessage("虚拟机[" + cloudServer.getName() + "]重置状态失败：" + e.getMessage());
                    resourceEventPublisher.send(result);
                }
            }).start();
            return new BocloudResult<>(true, "任务已经下发，正在执行...");
        } catch (Exception e) {
            logger.error("重置虚拟机状态失败：", e);
            return new BocloudResult<>(false, "重置虚拟机状态失败：" + e.getMessage());
        }
    }

    /**
     * 取消定时快照任务
     *
     * @param serverId
     * @param context
     * @return
     */
    @Override
    public BocloudResult cancelSnapshotTask(Long serverId, RequestContext context) {
        try {
            snapshotTaskService.removeByVmId(serverId);
            return new BocloudResult<>(true, "定时快照任务取消成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "定时快照任务取消失败");
        }
    }

    @Override
    public BocloudResult detachNetworks(Long id, Long portId, RequestContext context, String action) {
        // 卸载OpenStack虚拟机全部网卡
        if ("all".equalsIgnoreCase(action)) {
            return this.detachAllPorts(id, context);
        }
        // 卸载网卡(openstack)
        return this.detachNetwork(id, portId, context);
    }

    @Override
    public BocloudResult addPortPolicy(String params, RequestContext context) {
        JSONObject object = JSONTools.isJSONObj(params);
        if (null == object) {
            return new BocloudResult<>(false, "参数格式错误");
        }
        // 虚拟机ID
        Long id = object.getLong(Common.ID);
        // 端口ID
        Long portId = object.getLong("portId");
        // 云平台ID
        Long vendorId = object.getLong(Common.VENDORID);
        Long policyId = object.getLong("policyId");
        String path = CloudServer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            Port port = portRepository.query(portId);
            Optional.ofNullable(port).orElseThrow(() -> new Exception("端口不存在"));
            QosPolicy qosPolicy = qosPolicyRepository.query(policyId);
            Optional.ofNullable(qosPolicy).orElseThrow(() -> new Exception("QoS策略不存在"));
            BocloudResult result = serverDriver.addPortPolicy(vendor.getUuid(), server.getRegionId(),
                port.getPortUuid(), qosPolicy.getPolicyUuid());
            if (result.isFailed()) {
                return new BocloudResult<>(false, result.getMessage());
            }
            port.setQosPolicyUuid(qosPolicy.getPolicyUuid());
            port.setMaxKbps(qosPolicy.getMaxKbps());
            portRepository.update(port);
            server.setPrivateIps(serverOperationHelper.getPrivateIps(server, vendor));
            cloudServerRepository.update(server);
            return new BocloudResult<>(true, "QoS设置成功");
        } catch (Exception e) {
            logger.error("openstack CloudServer change qos fail:", e);
            return new BocloudResult<>(false, "QoS设置失败");
        }
    }

    @Override
    public BocloudResult resizes(VmModifyParam vmModifyParam, RequestContext context) {
        String action = vmModifyParam.getAction();
        if ("confirmResize".equalsIgnoreCase(action)) {
            return this.confirmResize(JSON.toJSONString(vmModifyParam), context);
        }
        if ("revertResize".equalsIgnoreCase(action)) {
            return this.revertResize(JSON.toJSONString(vmModifyParam), context);
        }
        // 升级配置
        if ("upgradeconfig".equalsIgnoreCase(action)) {
            return vmApplyService.upgradeConfig(JSON.toJSONString(vmModifyParam), context);
        }
        return this.resize(JSON.toJSONString(vmModifyParam), context);
    }

    @Override
    public BocloudResult flavors(String params, RequestContext context, String action) {
        JSONObject object = JSONTools.isJSONObj(params);
        Long serverId = object.getLong("id");
        // 查询高于虚拟机当前配置的规格 listFlavor
        if ("high".equalsIgnoreCase(action)) {
            return this.listFlavor(serverId, object.getLong(Common.VENDORID));
        }
        // 查询虚拟机规格queryFlavorByServerId
        return this.queryFlavorByServerId(serverId);
    }

    @Override
    public BocloudResult vmtools(Long id, VmModifyParam vmModifyParam, RequestContext context) {
        String action = vmModifyParam.getAction();
        // 挂载vmware tools安装镜像
        if ("mountToolsInstaller".equalsIgnoreCase(action)) {
            return this.mountToolsInstaller(id);
        } else if ("unmountToolsInstaller".equalsIgnoreCase(action)) {
            // 卸载vmware,tools安装镜像
            return this.unmountToolsInstaller(id);
        } else if ("upgradeToolsTask".equalsIgnoreCase(action)) {
            // 挂载或升级vmware,tools
            return this.upgradeToolsTask(id, vmModifyParam.getOptions(), context);
        } else if ("vmToolsConfig".equalsIgnoreCase(action)) {
            JSONObject object = JSONTools.isJSONObj(JSON.toJSONString(vmModifyParam));
            return this.vmToolsConfig(object, context.getTarget());
        } else if ("resetInstance".equalsIgnoreCase(action)) {
            return this.resetInstance(JSON.toJSONString(vmModifyParam), context);
        }
        return new BocloudResult<>(false, "无效操作！");
    }

    @Override
    public BocloudResult joinGroups(SecurityGroupOperationParam securityGroupOperationParam, RequestContext context) {
        if (null == securityGroupOperationParam) {
            return ResultTools.formatErrResult();
        }
        String action = securityGroupOperationParam.getAction();
        if ("batch".equalsIgnoreCase(action)) {
            // 批量加入安全组
            return this.batchJoinSGroup(securityGroupOperationParam.getId(), securityGroupOperationParam, context);
        } else if ("allocation".equalsIgnoreCase(action)) {
            return this.allocationSGroups(securityGroupOperationParam.getId(),
                JSON.toJSONString(securityGroupOperationParam), context);
        }
        // normal
        return this.joinSGroup(securityGroupOperationParam.getId(), securityGroupOperationParam.getGroupId(), context);
    }

    @Override
    public BocloudResult allocationSGroups(Long id, String params, RequestContext context) {
        String path = CloudServer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            JSONObject object = JSONObject.parseObject(params);
            Optional.ofNullable(object).orElseThrow(() -> new Exception("参数格式错误"));
            CloudServer server = cloudServerRepository.query(id);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            // 安全组验证
            List<String> groupUuids = new ArrayList<>();
            String groupIds = object.getString("groups");
            List<Long> groupIdsList = JSON.parseArray(groupIds, Long.class);
            if (null == groupIdsList || groupIdsList.size() == 0) {
                return new BocloudResult<>(false, "参数格式错误");
            }
            for (Long groupId : groupIdsList) {
                SecurityGroup group = securityGroupRepository.query(groupId);
                Optional.ofNullable(group).orElseThrow(() -> new Exception("安全组不存在"));
                groupUuids.add(group.getGroupUuid());
            }
            BocloudResult result = null;
            // 安全组验证
            if (CloudProvider.OPENSTACK.name().equalsIgnoreCase(vendor.getType())) {
                TenantProvider provider = vendorProjectService.getAncestorProject(vendor.getId(), server.getTenantId());
                String projectName = null;
                if (null != provider) {
                    projectName = provider.getProjectName();
                }
                result = serverDriver.allocationSGroups(server.getInstanceId(), groupUuids, vendor.getUuid(),
                    projectName, server.getRegionId());
            } else {
                result = serverDriver.allocationSGroups(server.getInstanceId(), groupUuids, vendor.getUuid(),
                    server.getRegionId());
            }
            if (result.isFailed()) {
                return new BocloudResult<>(false, result.getMessage());
            }
            serverSgroupRepository.removeBySid(server.getId());
            for (Long groupId : groupIdsList) {
                serverSgroupRepository.save(new ServerSgroup(server.getId(), groupId));
            }
            return new BocloudResult<>(true, "分配安全组成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult<>(false, "加入安全组失败");
        }
    }

    @Override
    public BocloudResult<List<SecurityGroup>> sgroups(Long id, RequestContext context, String action) {
        if ("bind".equalsIgnoreCase(action)) {
            return listSGroup(id);
        } else if ("unbind".equalsIgnoreCase(action) || "listunboundsgroup".equalsIgnoreCase(action)) {
            return listUnboundSGroup(id, context);
        } else if ("listsgroup".equalsIgnoreCase(action)) {
            return listSGroup(id);
        }
        return new BocloudResult<>(false, "无效操作！");
    }

    @Override
    public BocloudResult vncconsoles(Long id, String vncType, String serverId, String region, RequestContext context,
        String action) {
        if ("vc".equalsIgnoreCase(action)) {
            return this.vmrcConsole(id);
        }
        JSONObject params = new JSONObject();
        params.put("id", id);
        params.put("vncType", vncType);
        params.put("serverId", serverId);
        params.put("region", region);
        params.put("action", action);
        return this.vncconsole(params.toJSONString(), context);
    }

    @Override
    public BocloudResult vmToolsInstalls(String params, RequestContext context, String action) {
        if ("vmtoolsinstall".equalsIgnoreCase(action)) {
            return this.vmToolsInstall(params, context);
        } else if ("resetInstance".equalsIgnoreCase(action)) {
            // return this.resetInstance(params, context);
        }
        return new BocloudResult<>(false, "无效操作！");
    }

    @Override
    public BocloudResult<List<Keypair>> keypairs(Long id, RequestContext context, String action) {
        if ("bind".equalsIgnoreCase(action)) {
            return this.listBindedKeyPair(id);
        } else if ("unbind".equalsIgnoreCase(action)) {
            return this.listunBindKeyPair(id, context);
        }
        return new BocloudResult<>(false, "无效操作！");
    }

    @Override
    public BocloudResult bindKeypairs(KeypairParam keypairParam, RequestContext context) {
        String action = keypairParam.getAction();
        if ("bind".equalsIgnoreCase(action)) {
            return this.bindKeypair(keypairParam, context);
        } else if ("unbind".equalsIgnoreCase(action)) {
            return this.unbindKeypair(keypairParam, context);
        }
        return new BocloudResult<>(false, "无效操作！");
    }

    @Override
    public BocloudResult volumes(String params, String action, RequestContext context) {
        JSONObject object = JSONTools.isJSONObj(params);
        if (null == object) {
            return ResultTools.formatErrResult();
        } else if ("attach".equalsIgnoreCase(action)) {
            return this.attachVolume(object.getLong("serverId"), object.getObject("volume", Volume.class), context);
        } else if ("detach".equalsIgnoreCase(action)) {
            return this.detachVolume(object.getLong("serverId"), object.getLong("volumeId"), context);
        }
        return new BocloudResult<>(false, "无效操作！");
    }

    @Override
    public BocloudResult<List<Port>> ports(String params, RequestContext context, String action) {
        JSONObject object = JSONTools.isJSONObj(params);
        if ("listExtranetByVmId".equalsIgnoreCase(action)) {
            return portService.listExtranetByVmId(params);
        } else if ("listByVmId".equalsIgnoreCase(action)) {
            return portService.listByVmId(params);
        }
        return this.listPort(object.getLong(Common.ID), object.getLong(Common.VENDORID));
    }

    /**
     * 虚拟机规格变更(配额回滚在最外层调用)
     *
     * @param params
     * @param context
     * @return
     */
    @Override
    public BocloudResult cpuAndMemoryExpansion(JSONObject params, RequestContext context) {
        CloudServerBean serverBean = new CloudServerBean();
        serverBean.setId(params.getLong("vmId"));
        serverBean.setCpu(params.getInteger("cpu"));
        serverBean.setMemory(params.getBigDecimal("memory"));
        Long serverId = serverBean.getId();
        String path = CloudServer.class.getSimpleName() + "_" + serverId;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudServer server = this.cloudServerRepository.query(serverId);
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            // 修改配置后的CPU
            Integer cpu = serverBean.getCpu();
            // 修改配置后的内存
            BigDecimal memory = serverBean.getMemory();
            if (!CloudProvider.VMWARE.name().equals(vendor.getType())) {
                if (cpu < server.getCpu() || memory.compareTo(server.getMemory()) < 0) {
                    return new BocloudResult<>(false, "不能对虚拟机【" + server.getName() + "】进行降配操作!");
                }
            }
            String spec = cpu + "C(Cpu)/" + memory + "MB(Memory)/" + server.getDisk() + "GB(Disk)";
            CloudProvider provider = CloudProvider.valueOf(server.getVendorType());
            BocloudResult result = null;
            // 获取规格
            String flavorUuid = null;
            ServerModel model = new ServerModel();
            switch (provider) {
                case OPENSTACK:
                    List<Flavor> flavors = flavorRepository.listByVendorId(vendor.getId());
                    for (Flavor flavor : flavors) {
                        String flavorSpec = flavor.getCpu() + "C(Cpu)/" + flavor.getMemory() + "MB(Memory)/"
                            + flavor.getDisk() + "GB(Disk)";
                        if (flavorSpec.equals(spec)) {
                            flavorUuid = flavor.getFlavorUuid();
                            break;
                        }
                    }
                    if (StringUtils.isEmpty(flavorUuid)) {
                        FlavorModel flavorModel = new FlavorModel("flavor" + Calendar.getInstance().getTime().getTime(),
                            cpu.intValue(), memory, server.getDisk());
                        BocloudResult bocloudResult = flavorDriver.create(vendor.getUuid(), flavorModel);
                        if (bocloudResult.isFailed()) {
                            logger.error("no have flavor to adaptation");
                            return new BocloudResult<>(false, "该Openstack平台没有适配的规格");
                        }
                        Flavor flavor = serverOperationHelper.parseObject(bocloudResult.getData(), Flavor.class);
                        flavor.setVendorId(vendor.getId());
                        flavorRepository.save(flavor);
                        flavorUuid = flavor.getFlavorUuid();
                    }
                    result = serverDriver.resize(server.getInstanceId(), flavorUuid, vendor.getUuid(), null);
                    if (result.isSuccess()) {
                        // 确认配置
                        result = serverDriver.confirmResize(server.getInstanceId(), vendor.getUuid(), null);
                        if (result.isFailed()) {
                            // 回滚
                            serverDriver.revertResize(server.getInstanceId(), vendor.getUuid(), null);
                            return new BocloudResult<>(false, "虚拟机规格调整失败，确认修改时发生错误!");
                        }
                    }
                    result.setMessage("配置修改成功");
                    result.setSuccess(true);
                    break;
                case VMWARE:
                    if (BocloudStatus.Server.RUNNING.name().equals(server.getStatus())) {
                        if (!server.getCpuHotEnable() && cpu > server.getCpu()) {
                            return new BocloudResult<>(false, "请先开启虚拟机【" + server.getName() + "】CPU热插拔设置");
                        }
                        if (!server.getMemHotEnable() && memory.compareTo(server.getMemory()) > 0) {
                            return new BocloudResult<>(false, "请先开启虚拟机【" + server.getName() + "】内存热插拔设置");
                        }
                    }
                    model.setCpu(cpu.intValue() == server.getCpu().intValue() ? null : cpu);
                    model.setMemory(memory.intValue() == server.getMemory().intValue() ? null : memory);
                    model.setInstanceId(server.getInstanceId());
                    model.setName(server.getName());
                    Vdc vdc = vdcRepository.query(server.getVdcId());
                    Optional.ofNullable(vdc).orElseThrow(() -> new Exception("数据中心不存在"));
                    model.setVdcName(vdc.getName());
                    Server host = serverRepository.query(server.getHostId());
                    Optional.ofNullable(host).orElseThrow(() -> new Exception("所属主机不存在"));
                    result = serverDriver.modify(vendor.getUuid(), null, model);
                    break;
                default:
                    result = new BocloudResult<>(false, "暂不支持对此类型虚拟机进行配置变更操作");
                    break;
            }
            if (result.isSuccess()) {
                result.setMessage("虚拟机【" + server.getName() + "】配置变更成功");
                server.setCpu(cpu);
                server.setMemory(memory);
                server.setGmtModify(new Date());
                // 更新虚拟机数据
                cloudServerRepository.update(server);
                ResourceEvent event = new ResourceEvent(server.getId(), "规格变更", result.isSuccess() ? "成功" : "失败",
                    context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
                resourceEventRepository.save(event);
                List<CmdbInfo> infos = Lists.newArrayList();
                infos.add(CmdbInfoConvertor.getInfo(server, "modify", null));
                cmdbMessagePublisher.send(CmdbInfoConvertor.getModel(BoCloudService.IMS, infos));
            }
            return result;
        } catch (Exception e) {
            logger.error("Get error message：{}", e);
            return new BocloudResult<>(false, "虚拟机配置变更失败:" + e.getMessage());
        }
    }

    /**
     * 虚拟机增加磁盘(配额回滚在最外层调用)
     *
     * @param params
     * @param context
     * @return
     */
    @Override
    public BocloudResult diskExpansion(JSONObject params, RequestContext context) {
        CloudServerBean serverBean = new CloudServerBean();
        serverBean.setId(params.getLong("vmId"));
        serverBean.setDisks(JSONArray.parseArray(params.getString("disks"), Integer.class));
        String path = CloudServer.class.getSimpleName() + "_" + serverBean.getId();
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            CloudServer server = this.cloudServerRepository.query(serverBean.getId());
            Optional.ofNullable(server).orElseThrow(() -> new Exception("虚拟机不存在"));
            ObjectRelation relation = objectRelationRepository.get(server.getId(), ResourceCategory.Computer.name());
            Optional.ofNullable(relation).orElseThrow(() -> new Exception("虚拟机【" + server.getName() + "】资源关系不存在"));
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Optional.ofNullable(vendor).orElseThrow(() -> new Exception("云平台不存在"));
            List<Integer> disks = serverBean.getDisks();
            ServerModel model = new ServerModel(server.getName(), server.getInstanceId(), null);
            server.setGmtModify(new Date());
            CloudProvider provider = CloudProvider.valueOf(vendor.getType());
            List<VolumeModel> attachVolumes = new ArrayList<>();
            switch (provider) {
                case VMWARE:
                    List<StoreHost> storeHosts = storeHostRepository.list(server.getHostId(), "PM");
                    if (ListTool.isEmpty(storeHosts)) {
                        return new BocloudResult<>(false, "虚拟机【" + server.getName() + "】所在宿主机未挂载任何数据存储");
                    }
                    List<JSONObject> addDiskList = new ArrayList<>();
                    for (Integer disk : disks) {
                        Long storeId = storeHosts.get(new Random().nextInt(storeHosts.size())).getStoreId();
                        DataStore store = dataStoreRepository.query(storeId);
                        if (null != store) {
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put("storeName", store.getName());
                            jsonObject.put("addSize", disk);
                            addDiskList.add(jsonObject);
                        }
                    }
                    model.setAddDiskList(addDiskList);
                    BocloudResult bocloudResult = serverDriver.modify(vendor.getUuid(), null, model);
                    if (bocloudResult.isFailed()) {
                        return bocloudResult;
                    }
                    ServerModel serverModel =
                        JSONObject.parseObject(JSONObject.toJSONString(bocloudResult.getData()), ServerModel.class);
                    server.setDisk(serverModel.getDisk());
                    attachVolumes = serverModel.getDiskDevices();
                    break;
                case OPENSTACK:
                    List<VolumeModel> models = new ArrayList<>();
                    for (int i = 0; i < disks.size(); i++) {
                        VolumeModel volumeModel = new VolumeModel();
                        volumeModel.setSize(disks.get(i));
                        BocloudResult result = volumeDriver.create(vendor.getUuid(), null, volumeModel);
                        if (result.isFailed()) {
                            return new BocloudResult<>(false, "虚拟机【" + server.getName() + "】磁盘扩容失败");
                        }
                        volumeModel =
                            JSONObject.parseObject(JSONObject.toJSONString(result.getData()), VolumeModel.class);
                        Long start = System.currentTimeMillis();
                        boolean running = true;
                        while (running) {
                            if (System.currentTimeMillis() - start > 1000 * 60 * 5) {
                                volumeModel.setStatus(BocloudStatus.Server.EXCEPTION.name());
                                running = false;
                            }
                            BocloudResult detailResult =
                                volumeDriver.detail(volumeModel.getVolumeUuid(), vendor.getUuid(), null);
                            if (detailResult.isSuccess()) {
                                VolumeModel bean = JSONObject
                                    .parseObject(JSONObject.toJSONString(detailResult.getData()), VolumeModel.class);
                                String state = bean.getStatus();
                                if ("AVAILABLE".equalsIgnoreCase(state) || "IN_USE".equalsIgnoreCase(state)
                                    || "BACKING_UP".equalsIgnoreCase(state) || "UNATTACHED".equalsIgnoreCase(state)) {
                                    volumeModel.setStatus(state);
                                    volumeModel.setBootVolume(bean.getBootVolume());
                                    volumeModel.setSourceSnapshotId(bean.getSourceSnapshotId());
                                    running = false;
                                } else {
                                    Thread.sleep(3000L);
                                }
                            } else {
                                volumeModel.setStatus(BocloudStatus.Server.EXCEPTION.name());
                                running = false;
                            }
                        }
                        models.add(volumeModel);
                    }
                    // 挂载到虚拟机
                    for (VolumeModel volumeModel : models) {
                        BocloudResult result = volumeDriver.attach(vendor.getUuid(), null, server.getInstanceId(),
                            volumeModel.getVolumeUuid());
                        if (result.isFailed()) {
                            return new BocloudResult<>(false, "虚拟机【" + server.getName() + "】磁盘扩容失败");
                        }
                        volumeModel.setDeviceName(String.valueOf(result.getData()));
                        attachVolumes.add(volumeModel);
                    }
                    break;
                default:
                    return new BocloudResult<>(false, "平台暂不支持此操作");
            }
            if (CloudProvider.VMWARE == provider) {
                volumeRepository.removeByServerId(server.getId(), context.getTarget());
            }
            // 保存硬盘数据
            for (VolumeModel volumeModel : attachVolumes) {
                Volume volume = new Volume();
                BeanUtils.copyProperties(volumeModel, volume);
                volume.setDevice(volumeModel.getDeviceName());
                volume.preSave(context.getTarget(), context.getTarget(), server.getId(), vendor.getId(),
                    server.getProjectId());
                volume.setGmtCreate(new Date());
                volume.setServerId(server.getId());
                volume.setStatus("IN_USE");
                volumeRepository.save(volume);
                // openstack需要保存硬盘关系
                if (CloudProvider.OPENSTACK == provider) {
                    ObjectRelation objectRelation = new ObjectRelation(volume.getCreatorId(), volume.getId(), false,
                        ResourceCategory.Computer.name(), context.getCatalog().name(), volume.getSize());
                    objectRelation.setExpiredTime(relation.getExpiredTime());
                    objectRelationRepository.save(objectRelation);
                }
            }
            cloudServerRepository.update(server);
            return new BocloudResult<>(true, "虚拟机【" + server.getName() + "】磁盘扩容成功");
        } catch (Exception e) {
            logger.error("Get error message：{}", e);
            return new BocloudResult<>(false, "虚拟机磁盘扩容失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult removeByInstanceIds(String params, RequestContext context) {
        try {
            List<String> instanceIds = JSONArray.parseArray(params, String.class);
            List<CloudServer> servers = cloudServerRepository.listByInstanceId(instanceIds);
            for (CloudServer server : servers) {
                cloudServerService.remove(server.getId(), null, context);
            }
            return new BocloudResult<>(true, "删除成功");
        } catch (Exception e) {
            logger.error("Get error message：{}", e.getMessage());
            return new BocloudResult<>(false, e.getMessage());
        }
    }

    @Override
    public CloudServer getByInstanceId(String instanceId) {
        try {
            return cloudServerRepository.getByInstanceId(instanceId);
        } catch (Exception e) {
            logger.error("Get error message：{}", e.getMessage());
            return null;
        }
    }

    @Override
    public BocloudResult batchAttachNetwork(List<AttachNetworkParam> params, RequestContext context) {
        try {
            new Thread(() -> {
                for (AttachNetworkParam object : params) {
                    Long id = object.getId();
                    CloudServer server = cloudServerRepository.query(id);
                    if (null == server) {
                        resourceEventPublisher.send(new OperateResult(false, "ID为【" + id + "】虚机不存在！", "manageone.vm",
                            MapTools.simpleMap(Common.VENDORID, 1), OperateCategory.ResourceEvent, context));
                        continue;
                    }
                    Long vendorId = server.getVendorId();
                    CloudVendor vendor = cloudVendorRepository.query(vendorId);
                    String operate = vendor.getType().toLowerCase() + ".vm";
                    OperateResult message = new OperateResult(false, "网卡挂载失败", operate,
                        MapTools.simpleMap(Common.VENDORID, vendorId), OperateCategory.ResourceEvent, context);
                    try {
                        List<NetworkBean> beans = object.getNetworks();
                        NetworkBean networkBean = beans.get(0);
                        Router router = routerRepository.query(networkBean.getRouterId());
                        if (null == router) {
                            Optional.ofNullable(router).orElseThrow(() -> new Exception("ID为【" + id + "】的虚机网络数据异常！"));
                        }
                        ServerModel serverModel = new ServerModel();
                        serverModel.setInstanceId(server.getInstanceId());
                        List<AddressBean> addressBeans = networkBean.getAddresses();
                        if (!ListTool.isEmpty(addressBeans)) {
                            for (AddressBean address : addressBeans) {
                                if (address.getSubnetId() != null) {
                                    Subnet subnet = subnetRepository.query(address.getSubnetId());
                                    Optional.ofNullable(subnet).orElseThrow(() -> new Exception("网络下无可用子网"));
                                    address.setSubnetUuid(subnet.getSubnetUuid());
                                    address.setNetworkUuid(subnet.getNetworkUuid());
                                    networkBean.setNetworkUuid(subnet.getNetworkUuid());
                                    networkBean.setNetworkId(subnet.getNetworkId());
                                    address.setSubnetName(subnet.getName());
                                    String addr = address.getAddress();
                                    if (!StringUtils.isEmpty(addr)) {
                                        // 判断IP是否存在于指定网络的IP池中
                                        Ip ip = ipRepository.checkExist(addr, address.getSubnetId(), vendor.getId());
                                        if (null != ip) {
                                            message.setMessage("指定的IP地址【" + addr + "】已被使用");
                                            resourceEventPublisher.send(message);
                                            continue;
                                        }
                                    }
                                    List<AddressBean> addresses = new ArrayList<>();
                                    addresses.add(address);
                                    networkBean.setAddresses(addresses);
                                    List<NetworkBean> networkCards = new ArrayList<>();
                                    networkCards.add(networkBean);
                                    serverModel.setNetworkBeans(networkCards);
                                    // 挂载网卡
                                    OSTenant tenant = osTenantRepository.getByTenantUuid(server.getTenantUuid(),
                                        server.getVendorId());
                                    String projectName = null;
                                    if (null != tenant) {
                                        projectName = tenant.getName();
                                    }
                                    BocloudResult bocloudResult =
                                        serverDriver.attachNetwork(vendor.getUuid(), projectName, null, serverModel);
                                    if (bocloudResult.isSuccess()) {
                                        ServerModel model = serverOperationHelper.parseObject(bocloudResult.getData(),
                                            ServerModel.class);
                                        List<PortModel> ports = model.getPorts();
                                        PortModel portModel = null;
                                        List<Port> oldPorts =
                                            portRepository.listByDeviceId(server.getInstanceId(), server.getVendorId());
                                        Map<String, Port> portMap = Maps.newHashMap();
                                        for (Port oldPort : oldPorts) {
                                            portMap.put(oldPort.getPortUuid(), oldPort);
                                        }
                                        for (PortModel port : ports) {
                                            if (!portMap.containsKey(port.getPortUuid())) {
                                                portModel = port;
                                                break;
                                            }
                                        }
                                        Port port = new Port();
                                        BeanUtils.copyProperties(portModel, port);
                                        port.preSave(context.getTarget(), context.getTarget(), vendorId,
                                            networkBean.getNetworkId());
                                        port.setStatus(BocloudStatus.Network.RUNNING.name());
                                        portRepository.save(port);
                                        List<PortFixedIpModel> portFixedIps = portModel.getPortFixedIps();
                                        List<PortFixedIpModel> fixedIps = new ArrayList<>();
                                        PortFixedIpModel fixedIpModel = portFixedIps.get(0);
                                        fixedIps.add(fixedIpModel);
                                        OpenstackTransportor toolOS = new OpenstackTransportor(ipRepository,
                                            ipPoolRepository, subnetRepository, portFixedIpRepository);
                                        toolOS.batchSavePortFixedIp(fixedIps, port.getPortUuid(), port.getId(),
                                            vendorId);
                                        Ip ip = ipRepository.checkExist(fixedIpModel.getIpAddress(), subnet.getId(),
                                            vendorId);
                                        if (null == ip) {
                                            String mask = IPAddress.getIPAddress(fixedIpModel.getIpAddress())
                                                .getMask(subnet.getCidr());
                                            ip = new Ip(fixedIpModel.getIpAddress(), mask, subnet.getGateway(),
                                                subnet.getDnsNames(), vendorId, 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(), vendorId);
                                            if (null != pool) {
                                                ip.setPoolId(pool.getId());
                                            }
                                            ipRepository.save(ip);
                                        }
                                        server.setPrivateIps(serverOperationHelper.getPrivateIps(server, vendor));
                                        server.setRouterUuid(subnet.getVpcUuid());
                                        cloudServerRepository.update(server);
                                        // 同步资源表
                                        serverOperationHelper.syncOsVResource(vendorId, server, context.getTarget());
                                        message.setSuccess(true);
                                        message.setMessage(
                                            "【" + server.getName() + "】网卡【" + fixedIpModel.getIpAddress() + "】挂载成功");
                                    } else {
                                        message.setSuccess(false);
                                        message.setMessage(bocloudResult.getMessage());
                                    }
                                    ResourceEvent event = new ResourceEvent(server.getId(), "挂载网卡",
                                        bocloudResult.isSuccess() ? "成功" : "失败", context.getTarget(), new Date(), "VM",
                                        vendor.getId(), context.getCatalog());
                                    resourceEventRepository.save(event);
                                    resourceEventPublisher.send(message);
                                }
                            }
                        }

                    } catch (Exception e) {
                        logger.error("attach port to cloud server fail:", e);
                        message.setMessage("网卡挂载失败：" + e.getMessage());
                        resourceEventPublisher.send(message);
                    }
                }
            }).start();
            return new BocloudResult<>(true, "批量任务已下发，正在执行......");
        } catch (Exception e) {
            logger.error("批量挂载任务失败：" + e.getMessage());
            return new BocloudResult<>(false, "批量挂载任务失败：" + e.getMessage());
        }
    }

    @Override
    public BocloudResult diskOperation(DiskOperationParam params, RequestContext context) {
        try {
            Long serverId = params.getServerId();
            CloudServer server = cloudServerRepository.query(serverId);
            Assert.notNull(server, "虚拟机不存在");
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            String action = params.getAction();
            ResourceEvent event = null;
            switch (action) {
                case "create":
                case "resize":
                    // 配置开启虚拟机diskUUID
                    serverDriver.enableDiskUuid(server.getInstanceId(), vendor.getUuid());
                    Vdc vdc = vdcRepository.query(server.getVdcId());
                    Assert.notNull(vdc, "数据中心不存在");
                    Server host = serverRepository.query(server.getHostId());
                    Assert.notNull(host, "虚拟机所属主机不存在");
                    List<StoreHost> storeHosts = storeHostRepository.list(host.getId(), "PM");
                    Assert.notEmpty(storeHosts, "该虚拟机所属宿主机未绑定任何存储");
                    // 数据盘
                    List<JSONObject> addDataDisks = params.getAddDataDisks();
                    ServerModel model = new ServerModel(server.getName(), server.getCpu(), server.getMemory(), null,
                        server.getInstanceId());
                    model.setVdcName(vdc.getName());
                    Long storeId = storeHosts.get(new Random().nextInt(storeHosts.size())).getStoreId();
                    DataStore datastore = dataStoreRepository.query(storeId);
                    model.setDatastore(datastore.getName());
                    // 虚拟机数据盘
                    if (!ListTool.isEmpty(addDataDisks)) {
                        List<Integer> disks = new ArrayList<>();
                        List<String> dataStoreNames = new ArrayList<>();
                        for (JSONObject dataDiskObj : addDataDisks) {
                            Integer disk = dataDiskObj.getInteger("disk");
                            disks.add(disk);
                            dataStoreNames.add(datastore.getName());
                        }
                        model.setDisks(disks);
                        model.setDataStoreNames(dataStoreNames);
                    }
                    List<JSONObject> editDataDisks = params.getEditDataDisks();
                    // 要编辑的虚拟机磁盘设备
                    model.setEditDiskList(editDataDisks);
                    BocloudResult result = serverDriver.modify(vendor.getUuid(), null, model);
                    Assert.isTrue(result.isSuccess(), result.getMessage());
                    CloudServer vm =
                        JSONObject.parseObject(JSONObject.toJSONString(result.getData()), CloudServer.class);
                    server.setCpu(vm.getCpu());
                    server.setMemory(vm.getMemory());
                    server.setDisk(vm.getDisk());
                    server.setGmtModify(new Date());
                    cloudServerRepository.update(server);
                    event = new ResourceEvent(server.getId(), "添加硬盘", "成功", context.getTarget(), new Date(), "VM",
                        vendor.getId(), context.getCatalog());
                    resourceEventRepository.save(event);
                    new Thread(() -> {
                        String operate = vendor.getType().toLowerCase() + ".vm";
                        try {
                            List<Volume> volumes = volumeRepository.listByServerId(server.getId());
                            Map<String, Volume> oldMap = Maps.newHashMap();
                            for (Volume disk : volumes) {
                                oldMap.put(disk.getVolumeUuid(), disk);
                            }
                            List<Volume> newDiskDevices = vm.getDiskDevices();
                            // 新增的磁盘
                            List<Volume> addDiskDevices = new ArrayList<>();
                            BocloudResult lvmResult = null;
                            // 新增磁盘设置uuid
                            if (!ListTool.isEmpty(addDataDisks)) {
                                for (Volume newDiskDevice : newDiskDevices) {
                                    if (!oldMap.containsKey(newDiskDevice.getVolumeUuid())) {
                                        addDiskDevices.add(newDiskDevice);
                                    } else {
                                        Volume volume = oldMap.get(newDiskDevice.getVolumeUuid());
                                        if (!volume.getName().equals(newDiskDevice.getName())) {
                                            volume.setName(newDiskDevice.getName());
                                            volumeRepository.update(volume);
                                        }
                                    }
                                }
                                List<Volume> newAddDisks = new ArrayList<>();
                                for (Volume disk : addDiskDevices) {
                                    disk.preSave(context.getTarget(), context.getTarget(), 0L, server.getVendorId());
                                    disk.setServerId(server.getId());
                                    disk.setCatalog(Catalog.Manager);
                                    volumeRepository.save(disk);
                                    newAddDisks.add(disk);
                                }
                                Map<Long, Volume> usedVolumeMap = new HashMap<>(8);
                                if (!ListTool.isEmpty(addDataDisks)) {
                                    for (JSONObject addDataDisk : addDataDisks) {
                                        if (addDataDisk.containsKey("createLvm") && addDataDisk.getBoolean("createLvm")
                                            && !StringUtils.isEmpty(addDataDisk.getString("device"))) {
                                            String device = addDataDisk.getString("device");
                                            Volume existVolume = volumeRepository.getByLvmMntp(server.getId(), device);
                                            Volume findVolume = null;
                                            for (Volume newAddDisk : newAddDisks) {
                                                if (addDataDisk.getInteger("disk").equals(newAddDisk.getSize())
                                                    && !usedVolumeMap.containsKey(newAddDisk.getId())) {
                                                    usedVolumeMap.put(newAddDisk.getId(), newAddDisk);
                                                    findVolume = newAddDisk;
                                                    break;
                                                }
                                            }
                                            if (null != existVolume) {
                                                findVolume.setFileSystem(existVolume.getFileSystem());
                                                lvmResult = lvmService.lvmExtend(server, vendor, addDataDisk,
                                                    findVolume, context);
                                            } else {
                                                lvmResult = lvmService.lvmCreate(server, vendor, addDataDisk,
                                                    findVolume, context);
                                            }
                                            if (lvmResult.isFailed()) {
//                                                List<String> diskNames = new ArrayList<>();
//                                                for (Volume newAddDisk : newAddDisks) {
//                                                    diskNames.add(newAddDisk.getName());
//                                                }
//                                                this.diskOperation(DiskOperationParam.builder().serverId(server.getId())
//                                                    .action("delete").diskNames(diskNames).build(), context);
                                                //逻辑修改，如果挂载LVM失败，磁盘不需要删除，但需要在站内信中给出明确说明
                                                throw new Exception("lvm挂载失败，原因："+lvmResult.getMessage());
                                            }
                                        }
                                    }
                                }
                            } else {
                                SyncVmwareUtils utils = new SyncVmwareUtils(cloudServerRepository, dataStoreRepository,
                                    serverRepository, snapshotRepository, networkRepository, clusterRepository,
                                    storeHostRepository, networkCardRepository, portGroupRepository,
                                    networkHostRepository, serverConfigRepository, resourceRepository, ipRepository,
                                    imageRepository, volumeRepository);
                                List<DataStore> stores = dataStoreRepository.listByVendor(vendor.getId());
                                Map<String, DataStore> storeMap = new HashMap<>(8);
                                stores.forEach(s -> storeMap.put(s.getStoreVal(), s));
                                utils.syncDiskDevice(storeMap, volumes, newDiskDevices, server.getVdcId(),
                                    vendor.getId(), server.getId(), context.getTarget());
                                if (!ListTool.isEmpty(editDataDisks)) {
                                    // 处理lvm
                                    for (JSONObject editDataDisk : editDataDisks) {
                                        Volume findVolume = volumeRepository.getDiskByName(server.getId(),
                                            editDataDisk.getString("name"));
                                        Assert.notNull(findVolume, "硬盘不存在");
                                        if (!StringUtils.isEmpty(findVolume.getLvmMntp())) {
                                            findVolume.setFileSystem(findVolume.getFileSystem());
                                            lvmResult =
                                                lvmService.lvmResize(server, vendor, editDataDisk, findVolume, context);
                                            //如果lvm挂载失败，由于vc不提供缩盘，所以不做任何操作
                                        } else {
                                            String device = editDataDisk.getString("device");
                                            if (StringUtils.isEmpty(device)) {
                                                continue;
                                            }
                                            Volume existVolume = volumeRepository.getByLvmMntp(server.getId(), device);
                                            if (null != existVolume) {
                                                findVolume.setFileSystem(existVolume.getFileSystem());
                                                lvmResult = lvmService.lvmExtend(server, vendor, editDataDisk,
                                                    findVolume, context);
                                            } else {
                                                lvmResult = lvmService.lvmCreate(server, vendor, editDataDisk,
                                                    findVolume, context);
                                            }
                                            if (lvmResult.isFailed()) {
//                                                List<String> diskNames = new ArrayList<>();
//                                                diskNames.add(findVolume.getName());
//                                                this.diskOperation(DiskOperationParam.builder().serverId(server.getId())
//                                                        .action("delete").diskNames(diskNames).build(), context);
                                                //逻辑修改，如果挂载LVM失败，磁盘不需要删除，但需要在站内信中给出明确说明
                                                throw new Exception("lvm挂载失败，原因："+lvmResult.getMessage());
                                            }
                                        }
                                    }
                                }
                            }
                            if (null != lvmResult) {
                                resourceEventRepository.save(new ResourceEvent(server.getId(), "创建LVM", "成功",
                                    context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog()));
                                resourceEventPublisher
                                    .send(new OperateResult(lvmResult.isSuccess(), lvmResult.getMessage(), operate,
                                        MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                            }
                        } catch (Exception e) {
                            logger.error("Get error message:{}", e.getMessage());
                            resourceEventRepository.save(new ResourceEvent(server.getId(), "创建LVM", "失败",
                                context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog()));
                            resourceEventPublisher.send(new OperateResult(false, "lvm任务执行失败,原因："+e.getMessage(), operate,
                                MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                        }
                    }).start();
                    break;
                case "delete":
                    List<String> diskNames = params.getDiskNames();
                    Assert.notEmpty(diskNames, "未选择硬盘");
                    List<Volume> volumes = volumeRepository.listByNames(server.getId(), diskNames);
                    List<String> diskUuids = volumes.stream().map(volume -> volume.getVolumeUuid()).collect(Collectors.toList());
                    //无论是否存在lvm，都先执行worker卸载
                    BocloudResult deleteLvmDisk = deleteLvmDisk(diskUuids, server, vendor, context);
                    if (deleteLvmDisk.isFailed()&&!deleteLvmDisk.getMessage().contains("There was a problem while connecting")) {
                        Assert.isTrue(deleteLvmDisk.isSuccess(), deleteLvmDisk.getMessage());
                    }
                    result = serverDriver.deleteDisk(vendor.getUuid(), server.getInstanceId(), diskUuids);
                    Assert.isTrue(result.isSuccess(), result.getMessage());
                    Integer disk = 0;
                    for (Volume volume : volumes) {
                        disk += null == volume.getSize() ? 0 : volume.getSize();
                        volumeRepository.remove(volume.getId(), context.getTarget());
                    }
                    Integer oldDisk = null == server.getDisk() ? 0 : server.getDisk();
                    server.setDisk(oldDisk - disk < 0 ? 0 : oldDisk - disk);
                    server.setGmtModify(new Date());
                    cloudServerRepository.update(server);
                    break;
                default:
                    return new BocloudResult<>(false, "暂不支持");
            }
            return new BocloudResult<>(true, "操作成功");
        } catch (Exception e) {
            logger.error("Get error message:{}", e.getMessage());
            return new BocloudResult<>(false, e.getMessage());
        }
    }

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

    @Override
    public BocloudResult<List<PortGroup>> networkResources(String resourceIds, String type) {
        try {
            if (StringUtils.isEmpty(resourceIds) || StringUtils.isEmpty(type)) {
                return new BocloudResult<>(false, "参数格式错误");
            }
            List<Long> resIds = JSON.parseArray(resourceIds, Long.class);
            List<Server> serverIds = serverRepository.listByIds(resIds, type);
            List<PortGroup> groups = new ArrayList<>();
            for (Server server : serverIds) {
                BocloudResult<List<PortGroup>> networks = this.networks(server.getId());
                if (networks.isSuccess() && !ListTool.isEmpty(networks.getData())) {
                    groups.addAll(networks.getData());
                }
            }
            return new BocloudResult<>(true, groups, "查询网络成功");
        } catch (Exception e) {
            logger.error("查询网络异常：" + e.getMessage());
            return new BocloudResult<>(false, "查询网络异常：" + e.getMessage());
        }
    }

    @Override
    public BocloudResult selectAllByVendorId(Long vendorId, RequestContext context) {
        try {
            List<Map<String, Object>> res = cloudServerRepository.selectAllByVendorId(vendorId);
            return new BocloudResult<>(true, res, "云平台下虚拟机信息（个数、cpu、men、disk）统计成功");
        } catch (Exception e) {
            logger.error("查询失败：" + e.getMessage());
            return new BocloudResult<>(false, "云平台下虚拟机信息（个数、cpu、men、disk）统计失败：" + e.getMessage());
        }
    }
}