package com.bocloud.ims.service.resource.server;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.bocloud.ims.service.task.ResourceTaskNotice;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.compute.HmcHostDriver;
import com.bocloud.cmp.driver.compute.HostDriver;
import com.bocloud.cmp.driver.compute.HostSeaDriver;
import com.bocloud.cmp.driver.compute.OsHostDriver;
import com.bocloud.cmp.driver.compute.ServerDriver;
import com.bocloud.cmp.driver.network.NetworkDriver;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.HostModel;
import com.bocloud.cmp.model.HostOperateModel;
import com.bocloud.cmp.model.NetworkModel;
import com.bocloud.cmp.model.OsHost;
import com.bocloud.cmp.model.OsHosts;
import com.bocloud.cmp.model.ServerBean;
import com.bocloud.cmp.model.ServerModel;
import com.bocloud.cmp.model.powervc.PowervcConstant;
import com.bocloud.cmp.model.powervc.PowervcHmcServerModel;
import com.bocloud.common.encrypt.AESEncrptor;
import com.bocloud.common.encrypt.Encryptor;
import com.bocloud.common.enums.BoCloudService;
import com.bocloud.common.enums.ResourceCatalog;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.GridBean;
import com.bocloud.common.model.OperateResult;
import com.bocloud.common.model.Pager;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.common.utils.JSONTools;
import com.bocloud.common.utils.MapTools;
import com.bocloud.database.utils.QueryBuilder;
import com.bocloud.ims.entity.resource.CloudServer;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.Cluster;
import com.bocloud.ims.entity.resource.Port;
import com.bocloud.ims.entity.resource.SanFabric;
import com.bocloud.ims.entity.resource.Server;
import com.bocloud.ims.entity.resource.Storage;
import com.bocloud.ims.entity.resource.Volume;
import com.bocloud.ims.entity.resource.powervc.HostSeaAdapter;
import com.bocloud.ims.entity.resource.powervc.PowervcHmc;
import com.bocloud.ims.entity.resource.powervc.PowervcHmcServer;
import com.bocloud.ims.entity.resource.powervc.PowervcRedisKeyBuilder;
import com.bocloud.ims.interfaces.resource.ServerService;
import com.bocloud.ims.repository.powervc.PowervcHmcRepository;
import com.bocloud.ims.repository.powervc.PowervcHmcServerRepository;
import com.bocloud.ims.repository.resource.CloudServerRepository;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.ClusterNodeRepository;
import com.bocloud.ims.repository.resource.ClusterRepository;
import com.bocloud.ims.repository.resource.IpRepository;
import com.bocloud.ims.repository.resource.NetworkCardRepository;
import com.bocloud.ims.repository.resource.NetworkHostRepository;
import com.bocloud.ims.repository.resource.PortFixedIpRepository;
import com.bocloud.ims.repository.resource.PortRepository;
import com.bocloud.ims.repository.resource.ResourcePoolRepository;
import com.bocloud.ims.repository.resource.ResourceRepository;
import com.bocloud.ims.repository.resource.SanFabricRepository;
import com.bocloud.ims.repository.resource.ServerAssetsRepository;
import com.bocloud.ims.repository.resource.ServerConfigRepository;
import com.bocloud.ims.repository.resource.ServerRepository;
import com.bocloud.ims.repository.resource.ServerVolumeRepository;
import com.bocloud.ims.repository.resource.SnapshotRepository;
import com.bocloud.ims.repository.resource.StorageRepository;
import com.bocloud.ims.repository.resource.StoreHostRepository;
import com.bocloud.ims.repository.resource.VolumeRepository;
import com.bocloud.ims.service.model.cmdb.CmdbInfo;
import com.bocloud.ims.service.transporter.vendor.PowervcTransporter;
import com.bocloud.ims.service.utils.CmdbInfoConvertor;
import com.bocloud.ims.service.utils.CmdbMessagePublisher;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Lists;

@Service("powervcServerService")
public class PowervcServerServiceImpl extends ServerServiceImpl implements ServerService {
    private static OperateResult.OperateCategory operateCategory = OperateResult.OperateCategory.ResourceEvent;

    private static Logger logger = LoggerFactory.getLogger(PowervcServerServiceImpl.class);
    @Autowired
    private StorageRepository storageRepository;
    @Autowired
    private ServerVolumeRepository serverVolumeRepository;
    @Autowired
    private VolumeRepository volumeRepository;
    @Autowired
    private SanFabricRepository sanFabricRepository;
    @Autowired
    private PowervcHmcRepository powervcHmcRepository;
    @Autowired
    private PortRepository portRepository;
    @Autowired
    private PowervcHmcServerRepository powervcHmcServerRepository;
    @Autowired
    private HmcHostDriver hmcHostDriver;
    @Autowired
    private OsHostDriver osHostDriver;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ServerRepository serverRepository;
    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private CloudServerRepository cloudServerRepository;
    @Autowired
    private ServerConfigRepository serverConfigRepository;
    @Autowired
    private ServerAssetsRepository serverAssetsRepository;
    @Autowired
    private ResourceRepository resourceRepository;
    @Autowired
    private NetworkHostRepository networkHostRepository;
    @Autowired
    private ClusterNodeRepository clusterNodeRepository;
    @Autowired
    private ResourcePoolRepository resourcePoolRepository;
    @Autowired
    private StoreHostRepository storeHostRepository;
    @Autowired
    private ServerDriver serverDriver;
    @Autowired
    private SnapshotRepository snapshotRepository;
    @Autowired
    private NetworkCardRepository networkCardRepository;
    @Autowired
    private PortFixedIpRepository portFixedIpRepository;
    @Autowired
    private NetworkDriver networkDriver;
    @Autowired
    private IpRepository ipRepository;
    @Autowired
    private ClusterRepository clusterRepository;
    @Autowired
    private HostDriver hostDriver;
    @Autowired
    private HostSeaDriver hostSeaDriver;
    @Autowired
    private PowervcTransporter powervcTransportor;
    @Autowired
    private TaskExecutor taskExecutor;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private CmdbMessagePublisher cmdbMessagePublisher;
    @Autowired
    private ResourceTaskNotice resourceTaskNotice;
    @Override
    public BocloudResult create(HostOperateModel model, RequestContext context) {
        try {
            Encryptor encryptor = new AESEncrptor();
            if (!StringUtils.isEmpty(model.getPassword())) {
                model.setPassword(encryptor.decrypt(model.getPassword(), null));
            }
            // license节点数校验
            BocloudResult licenseResult = this.licenseCheck(model.getVendorId(), 1, 0);
            if (licenseResult.isFailed()) {
                return licenseResult;
            }
            Long vendorId = model.getVendorId();
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            if (null == vendor) {
                return new BocloudResult(false, "获取云供应商失败");
            }
            if (!CloudProvider.POWERVC.name().equals(vendor.getType())) {
                return new BocloudResult(false, "平台类型" + vendor.getType() + "错误!");
            }
            PowervcHmc powervcHmc = powervcHmcRepository.get(model.getHmcId());
            if (powervcHmc == null) {
                return new BocloudResult(false, "未找到HMC连接");
            }
            model.setHmcUuid(powervcHmc.getUuid());

            // 启动一个线程
            taskExecutor.execute(() -> {
                BocloudResult result = hostDriver.create(vendor.getUuid(), null, model);
                String type = vendor.getType();
                String operate = type.toLowerCase() + ".host";
                if (result.isSuccess() && null != result.getData()) {
                    try {
                        List<CmdbInfo> infos = Lists.newArrayList();
                        JSONObject host = JSON.parseObject((String) result.getData()).getJSONObject("host")
                                .getJSONObject("registration");
                        String hostName = host.getString("host_name");
                        BocloudResult listResult = hostDriver.list(vendor.getUuid(), null);
                        if (listResult.isSuccess()) {
                            List<HostModel> hostModels = JSONArray
                                    .parseArray(JSONObject.toJSONString(listResult.getData()), HostModel.class);
                            for (HostModel hostModelPowervc : hostModels) {
                                if (hostModelPowervc.getHostName().equals(hostName)) {
                                    // 更新主机信息
                                    powervcTransportor.insertOrUpdate(vendor, hostModelPowervc, context.getTarget());
                                    Server serverPowervc = serverRepository.getByHostName(hostName, vendorId);
                                    if (serverPowervc == null) {
                                        throw new RuntimeException("未找到服务器");
                                    }
                                    // 设定为默认的主机组
                                    Cluster defaultCluster = clusterRepository
                                            .queryByUuid(PowervcConstant.DEFAULT_OS_AGGREGATE_ID, vendorId);
                                    if (defaultCluster == null) {
                                        throw new RuntimeException("未找到默认的主机组");
                                    }
                                    serverPowervc.setClusterId(defaultCluster.getId());
                                    serverRepository.update(serverPowervc);
                                    //发送消息给cop
                                    resourceTaskNotice.sendPhysicalMessage(serverPowervc, ResourceTaskNotice.Action.UPDATE);
                                    // 同步主机Sea
                                    BocloudResult seaResult = hostSeaDriver.list(vendor.getUuid());
                                    if (seaResult.isFailed()) {
                                        throw new RuntimeException("创建主机成功，但是更新主机虚拟网络适配器失败");
                                    }
                                    List<HostSeaAdapter> seas = JSONArray.parseArray(
                                            JSONObject.toJSONString(seaResult.getData()), HostSeaAdapter.class);
                                    for (HostSeaAdapter sea : seas) {
                                        if (sea.getServerHost().equals(hostModelPowervc.getHostName())) {
                                            powervcTransportor.insertOrUpdate(vendor, sea, context.getTarget());
                                        }
                                    }
                                    // 创建个线程，更新主机的CPU时钟频率，该属性在Powervc添加主机后稍等一会才会有值
                                    taskExecutor.execute(() -> {
                                        HostOperateModel hostOperateModel = new HostOperateModel();
                                        hostOperateModel.setUuid(hostModelPowervc.getUuid());
                                        long start = System.currentTimeMillis();
                                        while (System.currentTimeMillis() - start < 5 * 60 * 1000) {
                                            BocloudResult bocloudResult = hostDriver.detail(vendor.getUuid(), null,
                                                    hostOperateModel);
                                            if (bocloudResult.isSuccess()) {
                                                HostModel hostDetail = (HostModel) bocloudResult.getData();
                                                if (hostDetail.getCpuHz() != null && hostDetail.getCpuHz() > 0) {
                                                    try {
                                                        powervcTransportor.insertOrUpdate(vendor, hostDetail,
                                                                context.getTarget());
                                                    } catch (Exception e) {
                                                        logger.error("延迟更新主机信息失败：", e);
                                                    }
                                                    //发送消息给cop
                                                    Server server = serverRepository.getByHostName(hostDetail.getHostName(), vendor.getId());
                                                    if(null != server){
                                                        //发送消息给cop
                                                        resourceTaskNotice.sendPhysicalMessage(serverPowervc, ResourceTaskNotice.Action.UPDATE);
                                                    }
                                                    logger.debug("延迟更新主机信息成功");
                                                    break;
                                                }
                                            } else {
                                                logger.error("延迟更新主机信息失败：{}", bocloudResult.getMessage());
                                            }
                                            try {
                                                logger.debug("正在延迟更新主机信息，3秒后重试...");
                                                Thread.sleep(3000);
                                            } catch (InterruptedException e) {
                                                logger.error("延迟更新主机信息失败：", e);
                                                Thread.currentThread().interrupt();
                                            }
                                        }
                                    });
                                    break;
                                }
                            }
                        }
                    } catch (Exception e) {
                        logger.error("Create host fail:", e);
                        resourceEventPublisher.send(new OperateResult(false, "添加宿主机失败", operate,
                                MapTools.simpleMap(Common.VENDORID, vendor.getId()),
                                OperateResult.OperateCategory.ResourceEvent, context));
                        return;
                    }
                }
                resourceEventPublisher.send(new OperateResult(result.isSuccess(), result.getMessage(), operate,
                        MapTools.simpleMap(Common.VENDORID, vendor.getId()),
                        OperateResult.OperateCategory.ResourceEvent, context));
            });
            return new BocloudResult(true, "添加任务已下发，正在执行……");
        } catch (Exception e) {
            logger.error("Create host fail:", e);
            return new BocloudResult(false, "添加失败");
        }
    }

    @Override
    public BocloudResult modify(String params, RequestContext context) {
        JSONObject object = JSONTools.isJSONObj(params);
        ServerBean bean = JSONObject.parseObject(params, ServerBean.class);

        String path = Server.class.getSimpleName() + "_" + bean.getId();
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            Server server = this.serverRepository.query(bean.getId());
            if (null == server) {
                logger.warn("Server data does not exist!");
                return new BocloudResult(false, "数据不存在");
            }
            if (null != server.getVendorId()) {
                CloudVendor cloudVendor = cloudVendorRepository.query(server.getVendorId());
                if (null == cloudVendor) {
                    logger.warn("cloudVendor data does not exist!");
                    return new BocloudResult(false, "平台不存在");
                }
                if (CloudProvider.POWERVC.name().equals(cloudVendor.getType())) {
                    long hmcId = object.getIntValue("hmcId");
                    PowervcHmc hmc = powervcHmcRepository.get(hmcId);
                    if (hmc == null) {
                        logger.warn("hmc data does not exist!");
                        return new BocloudResult(false, "HMC连接不存在");
                    }
                    BocloudResult bocloudResult = hmcHostDriver.getHosts(cloudVendor.getUuid(), hmc.getUuid());
                    if (bocloudResult.isFailed()) {
                        logger.warn("获取HMC的HOST列表失败：" + bocloudResult.getMessage());
                        return bocloudResult;
                    }
                    OsHosts hosts = (OsHosts) bocloudResult.getData();
                    boolean finded = false;
                    for (OsHost host : hosts.getHosts()) {
                        if (host.getName().equals(server.getHostname())) {
                            finded = true;
                            break;
                        }
                    }
                    if (!finded) {
                        return new BocloudResult(false,
                                "该HMC连接[" + hmc.getName() + "]并不包含主机[" + server.getName() + "]");
                    }
                    HostOperateModel model = new HostOperateModel();
                    model.setHostName(server.getHostname());
                    model.setHmcUuid(hmc.getUuid());
                    bocloudResult = hostDriver.modify(cloudVendor.getUuid(), null, model);
                    if (bocloudResult.isFailed()) {
                        logger.warn("修改主机的HMC连接失败:" + bocloudResult.getMessage());
                        return bocloudResult;
                    }
                    powervcHmcServerRepository.removeByServer(server.getId());
                    PowervcHmcServer powervcHmcServer = new PowervcHmcServer();
                    powervcHmcServer.setHmcId(hmc.getId());
                    powervcHmcServer.setServerId(server.getId());
                    powervcHmcServerRepository.save(powervcHmcServer);
                    return new BocloudResult(true, "修改成功");
                }
            }
            return new BocloudResult(false, "平台类型Powervc错误!!");
        } catch (Exception e) {
            logger.error("Modify server fail:", e);
            return new BocloudResult(false, "修改失败");
        }
    }

    @Override
    public BocloudResult remove(Long id, Boolean force, RequestContext context) {
        String path = Server.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            Server host = this.serverRepository.query(id);
            if (null == host) {
                logger.warn("Server data does not exist!");
                return new BocloudResult(false, "主机不存在");
            }
            if (null != host.getClusterId() && host.getMaintained() != null && !host.getMaintained()
                    && host.getConnected() != null && host.getConnected()) {
                return new BocloudResult(false, "存在于集群中的宿主机必须进入维护模式才能删除");
            }
            Long userId = context.getTarget();
            if (null == host.getVendorId()) {
                serverConfigRepository.removeBySid(id);
                serverAssetsRepository.removeBySid(id);
                serverRepository.remove(id, userId);
                resourceRepository.remove(id, ResourceCategory.Computer.name(), ResourceCatalog.PHYSICAL.name(),
                        userId);
                //通知主机资源
                resourceTaskNotice.sendPhysicalMessage(host, ResourceTaskNotice.Action.DEL);
                // 同步到cmdb
                List<CmdbInfo> infos = Lists.newArrayList();
                infos.add(CmdbInfoConvertor.getInfo(host, null, "delete", null));
                cmdbMessagePublisher.send(CmdbInfoConvertor.getModel(BoCloudService.IMS, infos));
                return new BocloudResult(true, id, "删除成功");
            }
            CloudVendor vendor = cloudVendorRepository.query(host.getVendorId());
            if (null == vendor) {
                return new BocloudResult(false, "获取云供应商失败");
            }
            if (!CloudProvider.POWERVC.name().equals(vendor.getType())) {
                return new BocloudResult(false, "平台类型" + vendor.getType() + "错误!");
            }
            taskExecutor.execute(() -> {
                // 移除宿主机
                HostOperateModel model = new HostOperateModel();
                model.setHostName(host.getHostname());
                model.setClusterName(host.getClusterName());
                BocloudResult result = hostDriver.remove(vendor.getUuid(), null, model);
                String type = vendor.getType();
                String operate = type.toLowerCase() + ".host";
                if (result.isSuccess()) {
                    try {
                        // 同步到cmdb
                        List<CmdbInfo> infos = Lists.newArrayList();
                        List<CloudServer> servers = cloudServerRepository.listByHid(id);
                        for (CloudServer server : servers) {
                            // 删除云主机下的快照
                            snapshotRepository.removeByVm(server.getId(), userId);
                            storeHostRepository.deleteByHost(server.getId(), "VM");
                            networkHostRepository.deleteByHost(server.getId(), "VM");
                            networkCardRepository.removeByHost(server.getId(), "VM", userId);
                            resourceRepository.remove(server.getId(), ResourceCategory.Computer.name(),
                                    ResourceCatalog.LOGICAL.name(), userId);
                            // 回收IP
                            ipRepository.delete(server.getId(), "VM", vendor.getId());
                            // cmdb删除云主机
                            infos.add(CmdbInfoConvertor.getInfo(server, "delete", null));
                        }
                        List<CloudServer> cloudServers = cloudServerRepository.listByHid(id);
                        // 删除云主机
                        cloudServerRepository.removeByHost(id, userId);
                        //通知主机资源
                        resourceTaskNotice.sendLogicalMessage(cloudServers, ResourceTaskNotice.Action.DEL);
                        // powervc需要删除主机和HMC的关联关系
                        powervcHmcServerRepository.removeByServer(id);

                        storeHostRepository.deleteByHost(id, "PM");
                        networkHostRepository.deleteByHost(id, "PM");
                        networkCardRepository.removeByHost(id, "PM", userId);
                        resourceRepository.remove(id, ResourceCategory.Computer.name(), ResourceCatalog.PHYSICAL.name(),
                                userId);
                        serverConfigRepository.removeBySid(id);
                        serverAssetsRepository.removeBySid(id);
                        serverRepository.remove(id, userId);
                        //通知主机资源
                        resourceTaskNotice.sendPhysicalMessage(host, ResourceTaskNotice.Action.DEL);
                        // cmdb删除宿主机
                        infos.add(CmdbInfoConvertor.getInfo(host, null, "delete", null));
                        cmdbMessagePublisher.send(CmdbInfoConvertor.getModel(BoCloudService.IMS, infos));
                        // 回收IP
                        ipRepository.delete(host.getId(), "PM", vendor.getId());
                        if (null != host.getClusterId()) {
                            clusterNodeRepository.removeByRid(host.getResourceId(), userId);
                        }
                        // 删除集群下的资源池信息
                        resourcePoolRepository.removeByOwner(id, "HOST", userId);
                    } catch (Exception e) {
                        logger.error("删除失败", e);
                        resourceEventPublisher.send(new OperateResult(false, "删除宿主机失败", operate,
                                MapTools.simpleMap(Common.VENDORID, vendor.getId()),
                                OperateResult.OperateCategory.ResourceEvent, context));
                        return;
                    }
                }
                resourceEventPublisher.send(new OperateResult(result.isSuccess(), result.getMessage(), operate,
                        MapTools.simpleMap(Common.VENDORID, vendor.getId()),
                        OperateResult.OperateCategory.ResourceEvent, context));
            });
            return new BocloudResult(true, "删除任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("Remove server fail:", e);
            return new BocloudResult(false, "删除失败");
        }
    }

    private void backgroundUpdatePowervcOnboardVM(CloudVendor vendor, Server server) {
        taskExecutor.execute(() -> {
            BocloudResult bocloudResult = osHostDriver.allServers(vendor.getUuid(), server.getHostname());
            if (bocloudResult.isSuccess()) {
                List<PowervcHmcServerModel> servers = JSON.parseObject(bocloudResult.getData().toString())
                        .getJSONArray("servers").toJavaList(PowervcHmcServerModel.class);
                // 过滤掉已经被管理进来的
                servers.removeIf(PowervcHmcServerModel::getManaged);
                // 放进redis
                String redisKey = PowervcRedisKeyBuilder.buildForVM(vendor.getId(), server.getId());
                redisTemplate.opsForValue().set(redisKey, JSON.toJSONString(servers));
            }
        });
    }

    @Override
    public BocloudResult listUnmanagedPowervm(int page, int rows, List<Param> params, Map<String, String> sorter,
                                              boolean simple) {
        try {
            Map<String, Object> paramMap = QueryBuilder.getParam(params);
            if (!paramMap.containsKey("id")) {
                return new BocloudResult(false, "查询失败: 需要查询参数id");
            }
            long serverId = Long.parseLong(paramMap.get("id").toString());// 服务器ID
            Server server = serverRepository.query(serverId);
            if (server == null) {
                return new BocloudResult(false, "查询失败，id为[" + serverId + "]的物理机不存在");
            }
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            if (null == vendor) {
                return new BocloudResult(false, "查询失败，id为[" + serverId + "]的所属平台不存在");
            }
            // 从redis或driver查询数据
            List<PowervcHmcServerModel> servers;
            String redisKey = PowervcRedisKeyBuilder.buildForVM(vendor.getId(), server.getId());
            String redisData = (String) redisTemplate.opsForValue().get(redisKey);
            if (!StringUtils.isEmpty(redisData)) {
                servers = JSON.parseArray(redisData, PowervcHmcServerModel.class);
            } else {
                // 后台更新可供管理的云主机，重新放到redis里面，这样等一会就可以使用了，就不用再等定时任务了
                backgroundUpdatePowervcOnboardVM(vendor, server);
                return new BocloudResult(false, "查询失败，数据正在更新中，请稍等几分钟后再试");
            }
            // 根据是否支持进行过滤
            if (paramMap.containsKey("support")) {
                boolean support = (boolean) paramMap.get("support");
                servers.removeIf(serverModel -> "supported".equals(serverModel.getSupport().getStatus()) != support);
            }
            // 根据名称进行过滤
            if (paramMap.containsKey("name")) {
                String name = (String) paramMap.get("name");
                servers.removeIf(serverModel -> !serverModel.getName().contains(name));
            }
            // 按名称排序以便分页
            servers.sort(Comparator.comparing(PowervcHmcServerModel::getName));
            // 计算总页数和起止行数
            int totalCount = servers.size();
            int pageStart = (page - 1) * rows;
            int pageEnd = page * rows;
            // 截取list
            List<PowervcHmcServerModel> resultVolumes;
            if (pageStart >= totalCount) {
                resultVolumes = new ArrayList<>();
            } else {
                resultVolumes = servers.subList(pageStart, Math.min(pageEnd, servers.size()));
            }
            GridBean gridBean = GridHelper.getBean(page, rows, totalCount, resultVolumes);
            return new BocloudResult(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("listUnmanagedPowervm failed:", e);
            return new BocloudResult(false, "查询失败", null, null);
        }
    }

    @Override
    public BocloudResult onboardPowervm(String params, RequestContext context) {
        JSONObject jsonObject = JSONTools.isJSONObj(params);
        if (null == jsonObject) {
            return new BocloudResult(false, "参数异常");
        }

        Long serverId = jsonObject.getLong("id");// 服务器ID
        String path = Server.class.getSimpleName() + "_" + serverId;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                logger.warn("Get harmonyLock time out!");
                return new BocloudResult(false, "请求超时");
            }

            Server server = serverRepository.query(serverId);
            if (server == null) {
                return new BocloudResult(false, "管理失败，id为[" + serverId + "]的物理机不存在");
            }
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            if (null == vendor) {
                return new BocloudResult(false, "管理失败，id为[" + serverId + "]物理机所属平台不存在");
            }
            List<Storage> storages = storageRepository.listByVendor(vendor.getId());
            if (storages == null || storages.size() == 0) {
                return new BocloudResult(false, "管理失败，请先添加存储器提供者");
            }
            List<SanFabric> sanFabrics = sanFabricRepository.listByVendor(vendor.getId());
            if (sanFabrics == null || sanFabrics.size() == 0) {
                return new BocloudResult(false, "管理失败，请先添加光纤网");
            }
            // 执行管理操作
            String operate = vendor.getType().toLowerCase() + ".host";
            JSONObject object = JSONObject.parseObject(params);
            List<String> serverUuids = JSONObject.parseArray(object.getString("servers"), String.class);
            if (null == serverUuids || serverUuids.isEmpty()) {
                logger.warn("params format is error!");
                return new BocloudResult(false, "参数格式不正确");
            }
            for (String serverUuid : serverUuids) {
                CloudServer cloudServer = cloudServerRepository.getByInstanceId(serverUuid, vendor.getId());
                if (cloudServer != null) {
                    return new BocloudResult(false, "云主机：" + serverUuid + "已经被管理");
                }
            }
            taskExecutor.execute(() -> {
                String content;
                boolean jobResult;
                try (BocloudACLock threadLock = lockFactory
                        .getACLock(Server.class.getName() + "_" + server.getId() + "onboard")) {
                    if (!threadLock.acquire(1, TimeUnit.DAYS)) {
                        resourceEventPublisher.send(new OperateResult(false, "管理现有云主机失败：请求超时", operate,
                                MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                        return;
                    }
                    BocloudResult listResult = osHostDriver.allServers(vendor.getUuid(), server.getHostname());
                    if (listResult.isFailed()) {
                        resourceEventPublisher
                                .send(new OperateResult(false, "管理现有云主机失败：" + listResult.getMessage(), operate,
                                        MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                        return;
                    }
                    List<PowervcHmcServerModel> servers = JSON.parseObject((String) listResult.getData())
                            .getJSONArray("servers").toJavaList(PowervcHmcServerModel.class);
                    for (String serverUuid : serverUuids) {
                        for (PowervcHmcServerModel model : servers) {
                            if (serverUuid.equals(model.getUuid()) && model.getManaged()) {
                                resourceEventPublisher.send(new OperateResult(false,
                                        "管理现有云主机失败：云主机" + model.getName() + "已经被管理，请重新选择", operate,
                                        MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                                return;
                            }
                        }
                    }
                    // 先清空redis，以免下次再查询可供管理云主机的时候从redis中获取到脏数据
                    String redisKey = PowervcRedisKeyBuilder.buildForVM(vendor.getId(), server.getId());
                    redisTemplate.delete(redisKey);
                    // 执行管理操作
                    BocloudResult onboardResult = osHostDriver.onboard(vendor.getUuid(), server.getHostname(),
                            serverUuids);
                    // 后台重新查询可供管理的云主机放到redis里面，避免定时任务间隔期间redis数据为空
                    backgroundUpdatePowervcOnboardVM(vendor, server);
                    // 将管理进来的云主机执行入库
                    @SuppressWarnings("unchecked")
                    List<ServerModel> successServers = (List<ServerModel>) onboardResult.getData();
                    for (ServerModel serverModel : successServers) {
                        powervcTransportor.syncCloudServer(vendor, serverModel, context.getTarget());
                    }
                    if (successServers.size() == serverUuids.size()) {
                        jobResult = true;
                        content = "管理现有云主机成功";
                    } else {
                        jobResult = false;
                        content = "管理现有云主机结果：" + successServers.size() + "成功，"
                                + (serverUuids.size() - successServers.size()) + "失败";
                    }
                    resourceEventPublisher.send(new OperateResult(jobResult, content, operate,
                            MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                    // 由于管理现有云主机以后，云主机的ip地址需要等一会才能拿到，所以这里延迟更新云主机的ip地址以及port数据
                    for (ServerModel serverModel : successServers) {
                        taskExecutor.execute(() -> {
                            long start = System.currentTimeMillis();
                            ServerModel getServerModel = null;
                            int failedCnt = 0;
                            while (System.currentTimeMillis() - start < 5 * 60 * 1000) {
                                try {
                                    if (failedCnt >= 10) {
                                        logger.error("延迟更新云主机[" + serverModel.getName() + "]信息失败：出现异常次数大于10次");
                                        break;
                                    }
                                    logger.info("正在延迟更新云主机[" + serverModel.getName() + "]信息，3秒后重试...");
                                    Thread.sleep(3000);
                                    BocloudResult getServerResult = serverDriver.detail(serverModel.getInstanceId(),
                                            vendor.getUuid(), null);
                                    if (getServerResult.isFailed()) {
                                        failedCnt++;
                                        logger.warn("延迟更新云主机[" + serverModel.getName() + "]信息失败：",
                                                getServerResult.getMessage());
                                        continue;
                                    }
                                    getServerModel = (ServerModel) getServerResult.getData();
                                    if (getServerModel == null) {
                                        failedCnt++;
                                        logger.warn("延迟更新云主机[" + serverModel.getName() + "]信息失败： 未查询到云主机信息");
                                        continue;
                                    }
                                    powervcTransportor.syncCloudServer(vendor, getServerModel, context.getTarget());
                                    JSONArray jsonArray = JSONArray.parseArray(getServerModel.getPrivateIps());
                                    if (jsonArray.size() != 0) {
                                        break;
                                    }
                                } catch (Exception e) {
                                    failedCnt++;
                                    logger.warn("延迟更新云主机[" + serverModel.getName() + "]信息失败：", e);
                                    continue;
                                }
                            }
                            logger.info("延迟更新云主机[" + serverModel.getName() + "]结束");
                        });
                    }
                } catch (Exception e) {
                    logger.error("Get Message Exception:", e);
                    resourceEventPublisher.send(new OperateResult(false, "管理powervc云主机失败", operate,
                            MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult(true, "管理powervc云主机任务已下发，正在执行……");
        } catch (Exception e) {
            logger.error("onboardPowervm failed:" + e.getMessage(), e);
            return new BocloudResult(false, "管理powervc云主机失败");
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public BocloudResult unmanagePowervm(String params, RequestContext context) {
        JSONObject jsonObject = JSONTools.isJSONObj(params);
        if (null == jsonObject) {
            return new BocloudResult(false, "参数异常");
        }
        Long serverId = jsonObject.getLong("id");// 服务器ID
        if (serverId == null) {
            return new BocloudResult(false, "无法取消对云主机的管理，因为不存在与它相关联的主机。请改为删除该云主机。");
        }
        String path = Server.class.getSimpleName() + "_" + serverId;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                logger.warn("Get harmonyLock time out!");
                return new BocloudResult(false, "请求超时");
            }

            Server server = serverRepository.query(serverId);
            if (server == null) {
                return new BocloudResult(false, "取消管理失败，id为[" + serverId + "]的物理机不存在");
            }
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            if (null == vendor) {
                return new BocloudResult(false, "取消管理失败，id为[" + serverId + "]物理机所属平台不存在");
            }
            String operate = vendor.getType().toLowerCase() + ".host";
            List<Long> cloudServerIds = jsonObject.getJSONArray("serverIds").toJavaList(Long.class);
            List<String> cloudServerUuids = new ArrayList<>(cloudServerIds.size());
            Map<CloudServer, String> cloudServers = new HashMap<>(cloudServerIds.size());
            for (Long cloudServerId : cloudServerIds) {
                CloudServer cloudServer = cloudServerRepository.query(cloudServerId);
                if (null == cloudServer) {
                    logger.error("Server does not exists!");
                    return new BocloudResult(false, "取消管理失败，id为[" + cloudServerId + "]云主机不存在");
                }
                cloudServers.put(cloudServer, cloudServer.getStatus());
                cloudServerUuids.add(cloudServer.getInstanceId());
                cloudServerRepository.update(cloudServer);
            }
            // 创建一个新的线程去执行
            taskExecutor.execute(() -> {
                try {
                    // 先清空redis，以免下次再查询可供管理云主机的时候从redis中获取到脏数据
                    String redisKey = PowervcRedisKeyBuilder.buildForVM(vendor.getId(), server.getId());
                    redisTemplate.delete(redisKey);
                    // 执行取消管理操作
                    BocloudResult result = osHostDriver.unmanage(vendor.getUuid(), server.getHostname(),
                            cloudServerUuids);
                    // 后台重新查询可供管理的云主机放到redis里面，避免定时任务间隔期间redis数据为空
                    backgroundUpdatePowervcOnboardVM(vendor, server);
                    // 开始从数据库中删除该云主机相关数据
                    @SuppressWarnings({"rawtypes"})
                    Map<String, List> resultMap = (Map<String, List>) result.getData();
                    List<String> successServerList = resultMap.get("successServerUuids");
                    List<String> successPortUuids = resultMap.get("successPortUuids");

                    for (Map.Entry<CloudServer, String> entry : cloudServers.entrySet()) {
                        if (successServerList.contains(entry.getKey().getInstanceId())) {
                            CloudServer serverToDelete = entry.getKey();
                            // 删除该云主机附加的卷
                            List<Volume> volumes = volumeRepository.listVolumeByServerId(serverToDelete.getId());
                            for (Volume volume : volumes) {
                                Pager pager = new Pager(1, Integer.MAX_VALUE, new ArrayList<>(), new HashMap<>());
                                List<CloudServer> servers = cloudServerRepository.listServerByVolumeId(volume.getId(), pager);
                                if (servers.size() == 1 && servers.get(0).getId().equals(serverToDelete.getId())) {
                                    volumeRepository.remove(volume.getId(), context.getTarget());
                                }
                            }
                            serverVolumeRepository.removeBySid(serverToDelete.getId());
                            // 将该云主机的port设定为锁定状态
                            List<Port> ports = portRepository.listByDeviceId(serverToDelete.getInstanceId(),
                                    vendor.getId());
                            for (Port port : ports) {
                                port.setDeviceUuid("Lock");
                                port.setDeviceOwner("Unmanaged VM " + serverToDelete.getName());
                                portRepository.update(port);
                            }
                            // 删除云主机
                            cloudServerRepository.remove(serverToDelete.getId(), context.getTarget());
                            //通知主机资源
                            resourceTaskNotice.sendLogicalMessage(serverToDelete, ResourceTaskNotice.Action.DEL);
                            List<CmdbInfo> infos = Lists.newArrayList();
                            infos.add(CmdbInfoConvertor.getInfo(serverToDelete, "delete", null));
                            cmdbMessagePublisher.send(CmdbInfoConvertor.getModel(BoCloudService.IMS, infos));
                        } else {
                            // 恢复云主机状态
                            entry.getKey().setStatus(entry.getValue());
                            cloudServerRepository.update(entry.getKey());
                            //通知主机资源
                            resourceTaskNotice.sendLogicalMessage(entry.getKey(), ResourceTaskNotice.Action.UPDATE);
                        }
                    }

                    // 管理进来的云主机可能会在现有的网络上创建一个没有ip地址的port，Driver中执行取消管理的时候会删除这些port并返回，这里数据库也跟着删除
                    for (String successPortUuid : successPortUuids) {
                        Port port = portRepository.getByPortUuid(successPortUuid, vendor.getId());
                        if (port != null && port.getVendorId().equals(vendor.getId())) {
                            portFixedIpRepository.deleteByPortId(port.getId());
                            portRepository.remove(port.getId(), context.getTarget());
                        }
                    }

                    // 管理现有云主机时，如果该云主机的vlanId在当前所有网络中都没有，则Powervc会创建一个新的网络，且该网络会在取消管理的时候可能一并删除，所以这里直接同步下所有网络信息
                    BocloudResult networkResult = networkDriver.list(vendor.getUuid(), null);
                    if (networkResult.isSuccess()) {
                        List<NetworkModel> networkModels = (List<NetworkModel>) networkResult.getData();
                        powervcTransportor.syncNetwork(vendor, networkModels, context.getTarget());
                    }

                    String message = result.isSuccess() ? "取消管理powervc云主机成功"
                            : "取消管理powervc云主机失败：" + result.getMessage();
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("Get Message Exception:", e);
                    resourceEventPublisher.send(new OperateResult(false, "取消管理powervc云主机失败", operate,
                            MapTools.simpleMap(Common.VENDORID, vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult(true, "取消管理powervc云主机任务已下发，正在执行……");
        } catch (Exception e) {
            logger.error("unmanagePowervm failed:" + e.getMessage(), e);
            return new BocloudResult(false, "取消管理powervc云主机失败");
        }
    }

    @Override
    public BocloudResult listByHmc(Long hmcId) {
        try {
            List<Server> servers = Lists.newArrayList();
            List<PowervcHmcServer> powervcHmcServers = powervcHmcServerRepository.listByHmcId(hmcId);
            for (PowervcHmcServer powervcHmcServer : powervcHmcServers) {
                Server server = serverRepository.query(powervcHmcServer.getServerId());
                if (server != null) {
                    servers.add(server);
                }
            }
            return new BocloudResult(true, servers, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message:", e);
            return new BocloudResult(false, "查询失败");
        }
    }

}
