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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.hmc.HmcVolumeGroupDriver;
import com.bocloud.cmp.entity.enums.HmcPartitionType;
import com.bocloud.cmp.model.hmc.sdk.module.*;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.OperateResult;
import com.bocloud.common.model.OperateResult.OperateCategory;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.model.Result;
import com.bocloud.common.utils.JSONTools;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.common.enums.HmcPartitionStatus;
import com.bocloud.ims.common.enums.HmcStatus;
import com.bocloud.ims.common.enums.ServerAction;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.ResourceEvent;
import com.bocloud.ims.entity.resource.hmc.*;
import com.bocloud.ims.entity.resource.hmc.params.*;
import com.bocloud.ims.interfaces.resource.hmc.HmcPartitionService;
import com.bocloud.ims.interfaces.resource.hmc.HmcVolumeGroupService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.ResourceEventRepository;
import com.bocloud.ims.repository.resource.hmc.*;
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;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

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

/**
 * HmcVolumeGroupServiceImpl
 *
 * @author lkx007
 */
@Service("HmcVolumeGroupService")
public class HmcVolumeGroupServiceImpl implements HmcVolumeGroupService {
    private static final Logger logger = LoggerFactory.getLogger(HmcVolumeGroupServiceImpl.class);
    private static OperateCategory operateCategory = OperateCategory.ResourceEvent;
    private static String operate = "vg.operate";
    private static String MESSAGE = "Unable to retrieve an equivalent object after the requested operation. "
            + "Note that this does not mean that the POST operation failed.";
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private HmcVolumeGroupDriver volumeGroupDriver;
    @Autowired
    private HmcPartitionRepository hmcPartitionRepository;
    @Autowired
    private HmcPhysicalDiskRepository hmcPhysicalDiskRepository;
    @Autowired
    private HmcVolumeGroupRepository hmcVolumeGroupRepository;
    @Autowired
    private HmcVirtualDiskRepository hmcVirtualDiskRepository;
    @Autowired
    private HmcVirtualCdRepository hmcVirtualCdRepository;
    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private HmcServerRepository hmcServerRepository;
    @Autowired
    private ResourceEventRepository resourceEventRepository;
    @Autowired
    private HmcPartitionScsiAdapterRepository hmcPartitionScsiAdapterRepository;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private HmcPhysicalFibreChannelRepository hmcPhysicalFibreChannelRepository;
    @Autowired
    private HmcVirtualFibreChannelMappingRepository hmcVirtualFibreChannelMappingRepository;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private HmcPartitionVfcAdapterRepository hmcPartitionVfcAdapterRepository;
    @Autowired
    private HmcPartitionNetworkAdapterRepository hmcPartitionNetworkAdapterRepository;
    @Autowired
    private HmcDatabaseHelper hmcDatabaseHelper;
    @Autowired
    private HmcPartitionService hmcPartitionService;

    @Override
    public BocloudResult<List<HmcVolumeGroup>> list(Long serverId, Long vendorId, Long viosId) {
        try {
            if (null == serverId || null == vendorId || null == viosId) {
                logger.error("param {} error", null == serverId ? serverId : (null == vendorId ? vendorId : viosId));
                return new BocloudResult(false, "参数异常");
            }

            List<HmcVolumeGroup> result = new ArrayList<>();
            List<HmcPartition> viosList = hmcPartitionRepository.list(vendorId, HmcPartitionType.VIOS.getType(),
                    serverId, HmcPartitionStatus.Running.getStatus());
            if (null != viosList && !viosList.isEmpty()) {
                for (HmcPartition vios : viosList) {
                    if (viosId.equals(vios.getId())) {
                        List<HmcVolumeGroup> volumeGroups = hmcVolumeGroupRepository.query(vios.getId(), null);
                        for (HmcVolumeGroup vg : volumeGroups) {
                            List<HmcVirtualDisk> hmcVirtualDisks = hmcVirtualDiskRepository
                                    .queryByVgIdViosId(vg.getId(), viosId);
                            for (HmcVirtualDisk vd : hmcVirtualDisks) {
                                if (vd.getAssignPartitionId() != null && vd.getAssignSlotId() != null) {
                                    HmcPartition lpar = hmcPartitionRepository.getById(vd.getAssignPartitionId());
                                    if (lpar != null) {
                                        vd.setAssign(lpar.getName() + "(" + lpar.getHmcPartitionId() + ")" + "-"
                                                + vd.getAssignSlotId());
                                        vd.setAssignStatus(lpar.getStatus());
                                    }
                                }
                            }
                            vg.setVirtualDisks(hmcVirtualDisks);
                            result.add(vg);
                        }
                    }
                }
            }
            return new BocloudResult(true, result, "查询卷组成功");
        } catch (Exception e) {
            logger.error("Query volume group failed:", e);
            return new BocloudResult(false, "查询卷组失败");
        }
    }

    @Override
    public BocloudResult<List<HmcPhysicalDisk>> listPd(Long serverId, Long vendorId, Long viosId) {
        try {
            if (null == serverId || null == vendorId || null == viosId) {
                logger.error("param {} error", null == serverId ? serverId : (null == vendorId ? vendorId : viosId));
                return new BocloudResult(false, "参数异常");
            }

            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            if (null == vendor) {
                logger.error("vendor {} does not exist!", vendorId);
                return new BocloudResult(false, "ID为[" + vendorId + "]的云平台不存在");
            }
            HmcServer hmcServer = hmcServerRepository.getServerById(serverId);
            if (null == hmcServer) {
                logger.error("hmcServer {} does not exist!", serverId);
                return new BocloudResult(false, "ID为[" + serverId + "]的小机不存在");
            }

            List<HmcPhysicalDisk> result = Lists.newArrayList();
            List<HmcPartition> viosList = hmcPartitionRepository.list(vendorId, HmcPartitionType.VIOS.getType(),
                    serverId, HmcPartitionStatus.Running.getStatus());
            if (null != viosList && !viosList.isEmpty()) {
                for (HmcPartition vios : viosList) {
                    if (viosId.equals(vios.getId())) {
                        List<HmcPhysicalDisk> pds = hmcPhysicalDiskRepository.query(vios.getId(), null);
                        for (HmcPhysicalDisk pd : pds) {
                            if (pd.getAssignPartitionId() != null && pd.getAssignSlotId() != null) {
                                HmcPartition lpar = hmcPartitionRepository.getById(pd.getAssignPartitionId());
                                if (lpar != null) {
                                    pd.setAssign(lpar.getName() + "(" + lpar.getHmcPartitionId() + ")" + "-"
                                            + pd.getAssignSlotId());
                                    pd.setAssignStatus(lpar.getStatus());
                                }
                            }
                            pd.setViosHmcId(vios.getHmcPartitionId());
                            pd.setViosName(vios.getName());
                            if (pd.getVgId() != null) {
                                pd.setVg(hmcVolumeGroupRepository.query(pd.getVgId()).getGroupName());
                            }
                            result.add(pd);
                        }
                    }
                }
            }
            return new BocloudResult(true, result, "查询物理卷成功");
        } catch (Exception e) {
            logger.error("Query physical disk failed:", e);
            return new BocloudResult(false, "查询物理卷失败");
        }
    }

    @Override
    public BocloudResult<List<HmcPhysicalFibreChannel>> listFc(Long partitionId) {
        try {
            if (null == partitionId) {
                logger.error("param {} error", partitionId);
                return new BocloudResult(false, "参数异常");
            }

            // 分区
            HmcPartition partition = this.hmcPartitionRepository.getById(partitionId);
            if (partition == null) {
                logger.warn("HMC partition does not exist!");
                return new BocloudResult(false, null, "分区不存在");
            }
            if (!"Virtual IO Server".equals(partition.getPartitionType())) {
                logger.warn("HMC partition is not VIOS");
                return new BocloudResult(false, null, "分区不是一个VIOS");
            }

            // 服务器
            HmcServer server = hmcServerRepository.getServerById(partition.getServerId());
            if (null == server) {
                logger.error("get HMC server failure!");
                return new BocloudResult(false, "服务器不存在!");
            }

            // 云平台
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            if (null == vendor) {
                logger.error("get cloudVendor failure!");
                return new BocloudResult(false, "云平台不存在!");
            }

            List<HmcPhysicalFibreChannel> fibreChannels = hmcPhysicalFibreChannelRepository
                    .listByPartitionId(partitionId);

            // 计算已经使用的虚拟光纤通道
            if (null != fibreChannels && !fibreChannels.isEmpty()) {
                for (HmcPhysicalFibreChannel fibreChannel : fibreChannels) {
                    int usedPorts = hmcVirtualFibreChannelMappingRepository.countByFc(partitionId,
                            fibreChannel.getUniqueDeviceId());
                    fibreChannel.setUsedPorts(usedPorts);
                }
            }

            return new BocloudResult(true, fibreChannels, "查询物理光纤通道成功");
        } catch (Exception e) {
            logger.error("Query physical disk failed:", e);
            return new BocloudResult(false, "查询物理光纤通道失败");
        }
    }

    @Override
    public BocloudResult<List<HmcVirtualFibreChannelMapping>> listFcMapping(Long partitionId, Long uniqueDeviceId) {
        try {
            if (null == partitionId) {
                logger.error("param {} error", partitionId);
                return new BocloudResult(false, "参数异常");
            }

            // 分区
            HmcPartition partition = this.hmcPartitionRepository.getById(partitionId);
            if (partition == null) {
                logger.warn("HMC partition does not exist!");
                return new BocloudResult(false, null, "分区不存在");
            }
            if (!"Virtual IO Server".equals(partition.getPartitionType())) {
                logger.warn("HMC partition is not VIOS");
                return new BocloudResult(false, null, "分区不是一个VIOS");
            }

            // 服务器
            HmcServer server = hmcServerRepository.getServerById(partition.getServerId());
            if (null == server) {
                logger.error("get HMC server failure!");
                return new BocloudResult(false, "服务器不存在!");
            }

            // 云平台
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            if (null == vendor) {
                logger.error("get cloudVendor failure!");
                return new BocloudResult(false, "云平台不存在!");
            }

            List<HmcVirtualFibreChannelMapping> mappings = hmcVirtualFibreChannelMappingRepository
                    .queryMappingByViosId(partitionId, uniqueDeviceId);

            // 根据hmc分区的标积ID，添加分区的名称和状态
            List<HmcVirtualFibreChannelMapping> mappingsToDelete = new ArrayList<>();
            for (HmcVirtualFibreChannelMapping mapping : mappings) {
                HmcPartition clientPartition = hmcPartitionRepository
                        .getByHmcPartitionId(mapping.getClientPartitionId(), partition.getServerId());
                if (null != clientPartition) {
                    mapping.setClientPartitionName(clientPartition.getName());
                    mapping.setPartitionStatus(clientPartition.getStatus());
                } else {
                    mapping.setClientPartitionName("分区不存在或者已被删除(" + mapping.getClientPartitionId() + ")");
                    mapping.setPartitionStatus(HmcPartitionStatus.Error.getStatus());
                }
            }
            mappings.removeAll(mappingsToDelete);
            return new BocloudResult(true, mappings, "查询虚拟光纤通道成功");
        } catch (Exception e) {
            logger.error("Query physical disk failed:", e);
            return new BocloudResult(false, "查询虚拟光纤通道失败");
        }
    }

    @Override
    public BocloudResult createVd(HmcVolumeGroupParams params, RequestContext context) {
        Long viosId = params.getViosId();
        String path = HmcVolumeGroupServiceImpl.class.getSimpleName() + viosId;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                logger.warn("Get harmonyLock time out!");
                return new BocloudResult(false, "该vios上处于繁忙状态，请稍后重试");
            }

            Long serverId = params.getServerId();
            Long vendorId = params.getVendorId();
            String diskName = params.getDiskName();
            String groupName = params.getGroupName();
            // hmc现在只支持6位的小数
            Double diskCapacity = Math.round(params.getDiskCapacity() * 1000000) / 1000000D;
            String assign = params.getAssign();
            JSONObject assignObject = JSONTools.isJSONObj(assign);
            if (null == serverId || null == vendorId || null == viosId || null == diskName || null == groupName
                    || null == diskCapacity || null == assignObject) {
                logger.error("param {} error", params);
                return new BocloudResult(false, "参数异常");
            }

            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            if (null == vendor) {
                logger.error("vendor {} does not exist!", vendorId);
                return new BocloudResult(false, "ID为[" + vendorId + "]的云平台不存在");
            }
            HmcServer hmcServer = hmcServerRepository.getServerById(serverId);
            if (null == hmcServer) {
                logger.error("hmcServer {} does not exist!", serverId);
                return new BocloudResult(false, "ID为[" + serverId + "]的小机不存在");
            }

            HmcPartition vios = hmcPartitionRepository.getById(viosId);
            if (null == vios) {
                logger.error("vios {} does not exist!", viosId);
                return new BocloudResult(false, "ID为[" + viosId + "]的vios不存在");
            }
            List<HmcVolumeGroup> vgs = hmcVolumeGroupRepository.query(vios.getId(), groupName);
            if (vgs.size() != 1) {
                logger.error("vg {} does not exist!", groupName);
                return new BocloudResult(false, "名称为[" + groupName + "]的vg不存在");
            }
            HmcVolumeGroup volumeGroup = vgs.get(0);

            // 虚拟磁盘名称在一个vios上必须唯一，即使是不同的vg
            HmcVirtualDisk vdByName = hmcVirtualDiskRepository.query(diskName, viosId);
            if (null != vdByName) {
                logger.error("virtual disk {} already exist!", diskName);
                return new BocloudResult(false, "名称为[" + diskName + "]的虚拟磁盘已经存在");
            }

            // 先保存创建中的信息
            HmcVirtualDisk entity = new HmcVirtualDisk();
            entity.setStatus(HmcStatus.DISK.CREATING.name());
            entity.setDiskName(diskName);
            entity.setDiskCapacity(diskCapacity);
            entity.setVgId(volumeGroup.getId());
            entity.setViosId(viosId);
            hmcVirtualDiskRepository.save(entity);

            // 启动一个线程进行虚拟盘的创建
            taskExecutor.submit(() -> {
                String content = "在vios[" + vios.getName() + "]上创建虚拟磁盘[" + diskName + "]成功";
                try {
                    ResourceEvent event = new ResourceEvent(vios.getId(), ServerAction.CREATE.name(), "虚拟磁盘创建成功",
                            context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                    // 创建虚拟磁盘
                    BocloudResult result = volumeGroupDriver.createVirtualDisk(vendor.getUuid(), vios.getUuid(),
                            volumeGroup.getUuid(), diskCapacity, diskName);
                    if (result.isFailed()) {
                        logger.error("create virtual disk failed:{}", result);
                        hmcVirtualDiskRepository.delete(entity);
                        event = new ResourceEvent(vios.getId(), ServerAction.CREATE.name(), "虚拟磁盘创建失败",
                                context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                        content = "在vios[" + vios.getName() + "]上创建虚拟磁盘[" + diskName + "]失败:" + result.getMessage();
                        resourceEventRepository.save(event);
                        resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                        return;
                    }

                    // 从查询结果中获取虚拟磁盘的信息
                    VolumeGroupEntry vg = (VolumeGroupEntry) result.getData();
                    for (VirtualDisk vd : vg.getContent().getVolumeGroup().getVirtualDisks().getDisks()) {
                        if (diskName.equals(vd.getDiskName())) {
                            entity.setDiskCapacity(Double.parseDouble(vd.getDiskCapacity()));
                            entity.setUniqueDeviceId(vd.getUniqueDeviceID());
                            entity.setDiskLabel(vd.getDiskLabel());
                            entity.setStatus(HmcStatus.DISK.NORMAL.name());
                        }
                    }

                    // 保存虚拟磁盘信息到数据库
                    hmcVirtualDiskRepository.updateEntity(entity);

                    // 更新volume group的可用大小信息
                    volumeGroup.setAvailableSize(
                            Double.parseDouble(vg.getContent().getVolumeGroup().getAvailableSize()));
                    volumeGroup.setFreeSpace(Double.parseDouble(vg.getContent().getVolumeGroup().getFreeSpace()));
                    hmcVolumeGroupRepository.updateEntity(volumeGroup);

                    // 将创建的虚拟磁盘按照要求进行分配
                    String partitionName = assignObject.getString("partitionName");
                    Long partitionId = assignObject.getLong("partitionId");
                    // 支持slot为null
                    Integer slot = assignObject.getInteger("slot");
                    if (assignObject != null && partitionName != null && partitionId != null) {
                        // 更新磁盘状态为分配中
                        entity.setStatus(HmcStatus.DISK.ASSIGNING.name());
                        hmcVirtualDiskRepository.updateEntity(entity);
                        HmcPartition clientLpar = hmcPartitionRepository.getById(partitionId);
                        if (null != clientLpar) {
                            result = volumeGroupDriver.assign(vendor.getUuid(), hmcServer.getUuid(), vios.getUuid(),
                                    clientLpar.getUuid(), diskName, String.valueOf(diskCapacity.intValue()),
                                    vios.getHmcPartitionId(), clientLpar.getHmcPartitionId(), slot, false);
                            // 分配虚拟盘失败，返回界面消息
                            if (result.isFailed() && !result.getMessage().contains(MESSAGE)) {
                                logger.error("create virtual disk success, assign failed:{}", result);
                                // 更新磁盘状态为分配失败
                                entity.setStatus(HmcStatus.DISK.ASSIGN_FAIL.name());
                                hmcVirtualDiskRepository.updateEntity(entity);
                                event = new ResourceEvent(vios.getId(), ServerAction.CREATE.name(), "虚拟磁盘创建成功，分配失败",
                                        context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                                content = "在vios[" + vios.getName() + "]上创建虚拟磁盘[" + diskName + "]成功，分配失败:"
                                        + result.getMessage();
                                resourceEventRepository.save(event);
                                resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                                        MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                                return;
                            }
                            // 分配虚拟盘成功，更新分配信息到数据库
                            VirtualIOServerEntry virtualIOServerEntry = (VirtualIOServerEntry) result.getData();
                            for (VirtualSCSIMapping mapping : virtualIOServerEntry.getContent().getVirtualIOServer()
                                    .getVirtualSCSIMappings().getVirtualScsiMapping()) {
                                if (mapping.getStorage() != null && mapping.getStorage().getVirtualDisk() != null
                                        && mapping.getStorage().getVirtualDisk().getUniqueDeviceID() != null
                                        && mapping.getServerAdapter() != null
                                        && mapping.getServerAdapter().getRemoteLogicalPartitionId() != null
                                        && mapping.getServerAdapter().getRemoteSlotNumber() != null) {
                                    if (mapping.getStorage().getVirtualDisk().getUniqueDeviceID()
                                            .equals(entity.getUniqueDeviceId())) {
                                        entity.setAssignPartitionId(getAssignPartitionId(
                                                mapping.getServerAdapter().getRemoteLogicalPartitionId(),
                                                vios.getServerId()));
                                        entity.setAssignSlotId(
                                                Integer.parseInt(mapping.getServerAdapter().getRemoteSlotNumber()));
                                        entity.setViosId(viosId);
                                        entity.setViosSlotId(Integer
                                                .parseInt(mapping.getServerAdapter().getVirtualSlotNumber()));
                                        entity.setStatus(HmcStatus.DISK.NORMAL.name());
                                        hmcVirtualDiskRepository.updateEntity(entity);
                                    }
                                }
                            }
                            // 创建虚拟盘，由于一条SCSI通道可以对应多个虚拟盘，所以这里直接同步vios的所有SCSI数据
                            hmcPartitionService.updateVirtualScsiAdapterForVios(vios, virtualIOServerEntry
                                    .getContent().getVirtualIOServer().getVirtualSCSIMappings());
                        }
                    }

                    resourceEventRepository.save(event);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("创建虚拟盘失败:", e);
                    content = "在vios[" + vios.getName() + "]上创建虚拟磁盘[" + diskName + "]失败:"
                            + e.getMessage();
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult(true, "创建虚拟磁盘的任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("create virtual disk failed:", e);
            return new BocloudResult(false, "创建失败");
        }
    }

    @Override
    public BocloudResult<List<HmcVirtualDisk>> listVd(Long serverId, Long vendorId, Long lparId) {
        try {
            if (null == serverId || null == vendorId || null == lparId) {
                logger.error("param {} error", null == serverId ? serverId : (null == vendorId ? vendorId : lparId));
                return new BocloudResult(false, "参数异常");
            }

            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            if (null == vendor) {
                logger.error("vendor {} does not exist!", vendorId);
                return new BocloudResult(false, "ID为[" + vendorId + "]的云平台不存在");
            }
            HmcServer hmcServer = hmcServerRepository.getServerById(serverId);
            if (null == hmcServer) {
                logger.error("hmcServer {} does not exist!", serverId);
                return new BocloudResult(false, "ID为[" + serverId + "]的小机不存在");
            }

            HmcPartition lpar = hmcPartitionRepository.getById(lparId);
            if (null == lpar) {
                logger.error("lpar {} does not exist!", lpar);
                return new BocloudResult(false, "ID为[" + lpar + "]的逻辑分区不存在");
            }

            List<HmcVirtualDisk> result = Lists.newArrayList();
            List<HmcPartition> viosList = hmcPartitionRepository.list(vendorId, HmcPartitionType.VIOS.getType(),
                    serverId, HmcPartitionStatus.Running.getStatus());
            if (null != viosList && !viosList.isEmpty()) {
                for (HmcPartition vios : viosList) {
                    List<HmcVirtualDisk> vds = hmcVirtualDiskRepository.queryByViosId(vios.getId());
                    for (HmcVirtualDisk vd : vds) {
                        if (vd.getAssignPartitionId() != null && lparId.equals(vd.getAssignPartitionId())) {
                            vd.setGroupName(hmcVolumeGroupRepository.query(vd.getVgId()).getGroupName());
                            vd.setViosName(vios.getName());
                            vd.setViosHmcId(vios.getHmcPartitionId());
                            vd.setAssignStatus(lpar.getStatus());
                            result.add(vd);
                        }
                    }
                }
            }

            return new BocloudResult(true, result, "查询虚拟磁盘成功");
        } catch (Exception e) {
            logger.error("Query virtual disk failed:", e);
            return new BocloudResult(false, "查询虚拟磁盘失败");
        }
    }

    private Long getAssignPartitionId(String lparId, Long serverId) {
        try {
            return hmcPartitionRepository.get(Integer.parseInt(lparId), serverId).getId();
        } catch (Exception e) {
            logger.error("get assign partition id from lparId {}, serverId {}, failed:", lparId, serverId, e);
            return null;
        }
    }

    @Override
    public BocloudResult<List<Object>> virtualSlotList(Long viosId, Long partitionId) {
        try {
            if (null == viosId || null == partitionId) {
                logger.error("param {} error", null == viosId ? viosId : partitionId);
                return new BocloudResult(false, "参数异常");
            }

            List<Object> result = Lists.newArrayList();
            List<Integer> slots = Lists.newArrayList();
            // 0和1为保留的插槽号，留给服务器串行适配器
            slots.add(0);
            slots.add(1);
            HmcPartition lpar = hmcPartitionRepository.getById(partitionId);
            if (null == lpar) {
                logger.error("lpar {} does not exist!", lpar);
                return new BocloudResult(false, "ID为[" + lpar + "]的lpar不存在");
            }

            // 如果分区正在运行，那么插槽号就已经被占用了
            if ("running".equalsIgnoreCase(lpar.getStatus()) || "migrating running".equalsIgnoreCase(lpar.getStatus())
                    || "starting".equalsIgnoreCase(lpar.getStatus())
                    || "open firmware".equalsIgnoreCase(lpar.getStatus())
                    || "shutting down".equalsIgnoreCase(lpar.getStatus())
                    || "suspending".equalsIgnoreCase(lpar.getStatus())) {
                List<HmcPartitionScsiAdapter> scsiAdapters = hmcPartitionScsiAdapterRepository
                        .queryByPartitionId(partitionId);
                for (HmcPartitionScsiAdapter scsiAdapter : scsiAdapters) {
                    slots.add(scsiAdapter.getAdapterId());
                }
                List<HmcVirtualDisk> vds = hmcVirtualDiskRepository.query(viosId, partitionId);
                for (HmcVirtualDisk vd : vds) {
                    slots.add(vd.getAssignSlotId());
                }
                // 查询虚拟光纤通道占用槽号
                List<HmcPartitionVfcAdapter> vfcs = hmcPartitionVfcAdapterRepository.listByViosAndPartition(viosId,
                        partitionId);
                for (HmcPartitionVfcAdapter vfc : vfcs) {
                    slots.add(vfc.getClientPartitionSlot());
                }
                // 查询以太网占用槽号
                List<HmcPartitionNetworkAdapter> networkAdapters = hmcPartitionNetworkAdapterRepository
                        .getByPartitionId(partitionId);
                for (HmcPartitionNetworkAdapter networkAdapter : networkAdapters) {
                    slots.add(networkAdapter.getAdapterId());
                }
            }
            // slots 去重
            HashSet<Integer> set = new HashSet<Integer>(slots);
            slots.clear();
            slots.addAll(set);
            for (Integer slot : slots) {
                Map<String, Object> scsi = Maps.newHashMap();
                scsi.put("partitionId", partitionId);
                scsi.put("slot", slot);
                result.add(scsi);
            }
            logger.info("get virtual slot result:{}", result);
            return new BocloudResult(true, result, "查询成功");
        } catch (Exception e) {
            logger.error("get virtual slot failed:", e);
            return new BocloudResult(false, "查询失败");
        }
    }

    @Override
    public BocloudResult assignPd(HmcVolumeGroupAssignParams params, RequestContext context) {
        Long viosId = params.getViosId();
        String path = HmcVolumeGroupServiceImpl.class.getSimpleName() + viosId;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Long serverId = params.getServerId();
            Long vendorId = params.getVendorId();
            String volumeName = params.getVolumeName();
            Long partitionId = params.getPartitionId();
            // 支持slot为null
            Integer slot = params.getSlot();
            if (null == serverId || null == vendorId || null == viosId || null == volumeName || null == partitionId) {
                logger.error("param {} error", params);
                return new BocloudResult(false, "参数异常");
            }
            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                logger.warn("Get harmonyLock time out!");
                return new BocloudResult(false, "该vios上处于繁忙状态，请稍后重试");
            }

            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            if (null == vendor) {
                logger.error("vendor {} does not exist!", vendorId);
                return new BocloudResult(false, "ID为[" + vendorId + "]的云平台不存在");
            }

            HmcServer hmcServer = hmcServerRepository.getServerById(serverId);
            if (null == hmcServer) {
                logger.error("hmcServer {} does not exist!", serverId);
                return new BocloudResult(false, "ID为[" + serverId + "]的小机不存在");
            }

            HmcPartition vios = hmcPartitionRepository.getById(viosId);
            if (null == vios) {
                logger.error("vios {} does not exist!", viosId);
                return new BocloudResult(false, "ID为[" + viosId + "]的vios不存在");
            }

            List<HmcPhysicalDisk> pds = hmcPhysicalDiskRepository.query(viosId, volumeName);
            if (pds.size() == 0) {
                logger.error("physical disk {} does not exist!", volumeName);
                return new BocloudResult(false, "名称为[" + volumeName + "]的物理磁盘不存在");
            }
            HmcPhysicalDisk pd = pds.get(0);

            HmcPartition clientLpar = hmcPartitionRepository.getById(partitionId);
            if (clientLpar == null || clientLpar.getHmcPartitionId() == null || clientLpar.getUuid() == null) {
                logger.error("client lpar {} does not exist!", partitionId);
                return new BocloudResult(false, "ID为[" + partitionId + "]的客户端lpar不存在");
            }

            if (pd.getAssignPartitionId() != null) {
                HmcPartition hmcPartition = hmcPartitionRepository.getById(pd.getAssignPartitionId());
                if (hmcPartition == null) {
                    logger.error("lpar {} does not exist!", pd.getAssignPartitionId());
                    return new BocloudResult(false, "ID为[" + pd.getAssignPartitionId() + "]的逻辑分区不存在");
                }
                if (HmcPartitionStatus.Running.getStatus().equals(hmcPartition.getStatus())
                        || HmcPartitionStatus.Open_Firmware.getStatus().equals(hmcPartition.getStatus())
                        || HmcPartitionStatus.Starting.getStatus().equals(hmcPartition.getStatus())
                        || HmcStatus.PARTITION.POWERON_RUNNING.getName().equals(hmcPartition.getStatus())
                        || HmcStatus.PARTITION.RESTART_RUNNING.getName().equals(hmcPartition.getStatus())) {
                    logger.error("lpar {} is running!", hmcPartition.getName());
                    return new BocloudResult(false, "请先将该卷已分配的逻辑分区[" + hmcPartition.getName() + "]关机");
                }
            }

            // TODO: 2020/8/31 这个极有可能V8也有同样的问题
            if ("V7".equals(vendor.getVersion())) {
                // 检查该vios是否存在这样的iscsi适配器：该适配器被分配了多个lv、pv、cd，如果存在则提示当前在不支持
                String multiAssignMsg = hmcDatabaseHelper.checkIscsiMultiAssign(viosId);
                if (StringUtils.isNotEmpty(multiAssignMsg)) {
                    return new BocloudResult(false, multiAssignMsg);
                }
            }

            // 启动一个线程进行物理盘的分配
            taskExecutor.submit(() -> {

                String content = "在vios[" + vios.getName() + "]上分配物理磁盘[" + volumeName + "]成功";
                try {
                    ResourceEvent event = new ResourceEvent(vios.getId(), ServerAction.UPDATE.name(), "物理磁盘分配成功",
                            context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                    // 分配虚拟磁盘
                    BocloudResult result = volumeGroupDriver.assign(vendor.getUuid(), hmcServer.getUuid(),
                            vios.getUuid(), clientLpar.getUuid(), volumeName,
                            String.valueOf(pd.getVolumeCapacity().intValue()), vios.getHmcPartitionId(),
                            clientLpar.getHmcPartitionId(), slot, true);
                    if (result.isFailed() && !result.getMessage().contains(MESSAGE)) {
                        event = new ResourceEvent(vios.getId(), ServerAction.UPDATE.name(), "物理磁盘分配失败",
                                context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                        content = "在vios[" + vios.getName() + "]上分配物理磁盘[" + volumeName + "]失败:"
                                + result.getMessage();
                    } else {
                        // get viso info and update pdisk database info
                        VirtualIOServerEntry virtualIOServerEntry = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), VirtualIOServerEntry.class);
                        List<VirtualSCSIMapping> mappings = virtualIOServerEntry.getContent().getVirtualIOServer()
                                .getVirtualSCSIMappings().getVirtualScsiMapping();
                        for (VirtualSCSIMapping mapping : mappings) {
                            if (mapping.getServerAdapter() != null
                                    && mapping.getServerAdapter().getRemoteLogicalPartitionId() != null
                                    && mapping.getServerAdapter().getRemoteSlotNumber() != null) {
                                if (volumeName.equals(mapping.getServerAdapter().getBackingDeviceName())) {
                                    pd.setAssignPartitionId(getAssignPartitionId(
                                            mapping.getServerAdapter().getRemoteLogicalPartitionId(),
                                            vios.getServerId()));
                                    pd.setAssignSlotId(
                                            Integer.parseInt(mapping.getServerAdapter().getRemoteSlotNumber()));
                                    pd.setViosId(viosId);
                                    pd.setViosSlotId(
                                            Integer.parseInt(mapping.getServerAdapter().getVirtualSlotNumber()));
                                    hmcPhysicalDiskRepository.updateEntity(pd);
                                }
                            }
                        }
                    }
                    resourceEventRepository.save(event);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("分配物理盘失败:", e);
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult(true, "分配物理磁盘的任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("assign virtual disk failed:", e);
            return new BocloudResult(false, "分配物理磁盘失败");
        }
    }

    @Override
    public BocloudResult assignVd(HmcVolumeGroupAssignParams params, RequestContext context) {
        Long viosId = params.getViosId();
        String path = HmcVolumeGroupServiceImpl.class.getSimpleName() + viosId;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Long serverId = params.getServerId();
            Long vendorId = params.getVendorId();
            Long vgId = params.getVgId();
            String diskName = params.getDiskName();
            Long partitionId = params.getPartitionId();
            // 支持slot为null
            Integer slot = params.getSlot();
            if (null == serverId || null == vendorId || null == viosId || null == vgId || null == diskName
                    || null == partitionId) {
                logger.error("param {} error", params);
                return new BocloudResult(false, "参数异常");
            }

            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                logger.warn("Get harmonyLock time out!");
                return new BocloudResult(false, "该vios上处于繁忙状态，请稍后重试");
            }

            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            if (null == vendor) {
                logger.error("vendor {} does not exist!", vendorId);
                return new BocloudResult(false, "ID为[" + vendorId + "]的云平台不存在");
            }

            HmcServer hmcServer = hmcServerRepository.getServerById(serverId);
            if (null == hmcServer) {
                logger.error("hmcServer {} does not exist!", serverId);
                return new BocloudResult(false, "ID为[" + serverId + "]的小机不存在");
            }

            HmcPartition vios = hmcPartitionRepository.getById(viosId);
            if (null == vios) {
                logger.error("vios {} does not exist!", viosId);
                return new BocloudResult(false, "ID为[" + viosId + "]的vios不存在");
            }

            HmcVirtualDisk vd = hmcVirtualDiskRepository.query(diskName, viosId, vgId);
            if (null == vd) {
                logger.error("virtual disk {} does not exist!", diskName);
                return new BocloudResult(false, "名称为[" + diskName + "]的虚拟磁盘不存在");
            }

            if (vd.getAssignPartitionId() != null) {
                HmcPartition hmcPartition = hmcPartitionRepository.getById(vd.getAssignPartitionId());
                if (hmcPartition == null) {
                    logger.error("lpar {} does not exist!", vd.getAssignPartitionId());
                    return new BocloudResult(false, "ID为[" + vd.getAssignPartitionId() + "]的逻辑分区不存在");
                }
                if (HmcPartitionStatus.Running.getStatus().equals(hmcPartition.getStatus())
                        || HmcPartitionStatus.Open_Firmware.getStatus().equals(hmcPartition.getStatus())
                        || HmcPartitionStatus.Starting.getStatus().equals(hmcPartition.getStatus())
                        || HmcStatus.PARTITION.POWERON_RUNNING.getName().equals(hmcPartition.getStatus())
                        || HmcStatus.PARTITION.RESTART_RUNNING.getName().equals(hmcPartition.getStatus())) {
                    logger.error("lpar {} is running!", hmcPartition.getName());
                    return new BocloudResult(false, "请先将该卷已分配的逻辑分区[" + hmcPartition.getName() + "]关机");
                }
            }

            // 检查磁盘状态
            if (HmcStatus.DISK.CREATING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.UPDATING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.DELETING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.ASSIGNING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.UNASSIGNING.name().equals(vd.getStatus())) {
                logger.error("virtual disk {} 状态为{}，不能执行分配操作!", vd.getDiskName(), vd.getStatus());
                return new BocloudResult(false, "虚拟磁盘" + diskName + "不能执行分配操作");
            }

            HmcPartition clientLpar = hmcPartitionRepository.getById(partitionId);
            if (clientLpar == null || clientLpar.getHmcPartitionId() == null || clientLpar.getUuid() == null) {
                logger.error("client lpar {} does not exist!", partitionId);
                return new BocloudResult(false, "ID为[" + partitionId + "]的客户端lpar不存在");
            }

            // TODO: 2020/8/31 这个极有可能V8也有同样的问题
            if ("V7".equals(vendor.getVersion())) {
                // 检查该vios是否存在这样的iscsi适配器：该适配器被分配了多个lv、pv、cd，如果存在则提示当前在不支持
                String multiAssignMsg = hmcDatabaseHelper.checkIscsiMultiAssign(viosId);
                if (StringUtils.isNotEmpty(multiAssignMsg)) {
                    return new BocloudResult(false, multiAssignMsg);
                }
            }

            vd.setStatus(HmcStatus.DISK.ASSIGNING.name());
            hmcVirtualDiskRepository.updateEntity(vd);

            // 启动一个线程进行虚拟盘的创建
            taskExecutor.submit(() -> {

                String content = "在vios[" + vios.getName() + "]上分配虚拟磁盘[" + diskName + "]成功";
                try {
                    ResourceEvent event = new ResourceEvent(vios.getId(), ServerAction.UPDATE.name(), "虚拟磁盘分配成功",
                            context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                    // 分配虚拟磁盘
                    BocloudResult result = volumeGroupDriver.assign(vendor.getUuid(), hmcServer.getUuid(),
                            vios.getUuid(), clientLpar.getUuid(), diskName,
                            String.valueOf(vd.getDiskCapacity().intValue()), vios.getHmcPartitionId(),
                            clientLpar.getHmcPartitionId(), slot, false);
                    if (result.isFailed() && !result.getMessage().contains(MESSAGE)) {
                        event = new ResourceEvent(vios.getId(), ServerAction.UPDATE.name(), "虚拟磁盘分配失败",
                                context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                        content = "在vios[" + vios.getName() + "]上分配虚拟磁盘[" + diskName + "]失败:" + result.getMessage();
                        vd.setStatus(HmcStatus.DISK.ASSIGN_FAIL.name());
                        hmcVirtualDiskRepository.updateEntity(vd);
                    } else {
                        // get viso info and update vdisk database info
                        VirtualIOServerEntry virtualIOServerEntry = (VirtualIOServerEntry) result.getData();
                        List<VirtualSCSIMapping> mappings = virtualIOServerEntry.getContent().getVirtualIOServer()
                                .getVirtualSCSIMappings().getVirtualScsiMapping();
                        for (VirtualSCSIMapping mapping : mappings) {
                            if (mapping.getStorage() != null && mapping.getStorage().getVirtualDisk() != null
                                    && mapping.getStorage().getVirtualDisk().getUniqueDeviceID() != null
                                    && mapping.getServerAdapter() != null
                                    && mapping.getServerAdapter().getRemoteLogicalPartitionId() != null
                                    && mapping.getServerAdapter().getRemoteSlotNumber() != null) {
                                if (mapping.getStorage().getVirtualDisk().getUniqueDeviceID()
                                        .equals(vd.getUniqueDeviceId())) {

                                    // 更新虚拟盘数据
                                    vd.setAssignPartitionId(getAssignPartitionId(
                                            mapping.getServerAdapter().getRemoteLogicalPartitionId(),
                                            vios.getServerId()));
                                    vd.setAssignSlotId(
                                            Integer.parseInt(mapping.getServerAdapter().getRemoteSlotNumber()));
                                    vd.setViosId(viosId);
                                    vd.setViosSlotId(
                                            Integer.parseInt(mapping.getServerAdapter().getVirtualSlotNumber()));
                                    vd.setStatus(HmcStatus.DISK.NORMAL.name());
                                    hmcVirtualDiskRepository.updateEntity(vd);
                                }
                            }
                        }
                        // 重新分配虚拟盘，由于一条SCSI通道可以对应多个虚拟盘，所以这里直接同步vios的所有SCSI数据
                        hmcPartitionService.updateVirtualScsiAdapterForVios(vios,
                                virtualIOServerEntry.getContent().getVirtualIOServer().getVirtualSCSIMappings());
                    }
                    resourceEventRepository.save(event);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("分配虚拟盘失败:", e);
                    content = "分配虚拟盘失败: " + e.getMessage();
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult(true, "分配虚拟磁盘的任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("assign virtual disk failed:", e);
            return new BocloudResult(false, "分配虚拟磁盘失败");
        }
    }

    @Override
    public BocloudResult update(HmcVolumeGroupUpdateParams params, RequestContext context) {
        Long viosId = params.getViosId();
        String path = HmcVolumeGroupServiceImpl.class.getSimpleName() + viosId;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Long serverId = params.getServerId();
            Long vendorId = params.getVendorId();

            Long vgId = params.getVgId();
            String diskName = params.getDiskName();
            String groupName = params.getGroupName();
            // hmc现在只支持6位的小数
            Double diskCapacity = Math.round(params.getDiskCapacity() * 1000000) / 1000000D;
            if (null == serverId || null == vendorId || null == viosId || null == diskName || null == groupName
                    || null == diskCapacity || null == vgId) {
                logger.error("param {} error", params);
                return new BocloudResult(false, "参数异常");
            }

            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                logger.warn("Get harmonyLock time out!");
                return new BocloudResult(false, "该vios上处于繁忙状态，请稍后重试");
            }

            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            if (null == vendor) {
                logger.error("vendor {} does not exist!", vendorId);
                return new BocloudResult(false, "ID为[" + vendorId + "]的云平台不存在");
            }
            HmcServer hmcServer = hmcServerRepository.getServerById(serverId);
            if (null == hmcServer) {
                logger.error("hmcServer {} does not exist!", serverId);
                return new BocloudResult(false, "ID为[" + serverId + "]的小机不存在");
            }

            HmcPartition vios = hmcPartitionRepository.getById(viosId);
            if (null == vios) {
                logger.error("vios {} does not exist!", viosId);
                return new BocloudResult(false, "ID为[" + viosId + "]的vios不存在");
            }
            List<HmcVolumeGroup> vgs = hmcVolumeGroupRepository.query(vios.getId(), groupName);
            if (vgs.size() != 1) {
                logger.error("vg {} does not exist!", groupName);
                return new BocloudResult(false, "名称为[" + groupName + "]的vg不存在");
            }
            HmcVirtualDisk vd = hmcVirtualDiskRepository.query(diskName, viosId, vgId);
            if (null == vd) {
                logger.error("virtual disk {} does not exist!", diskName);
                return new BocloudResult(false, "名称为[" + diskName + "]的虚拟磁盘不存在");
            }
            // 检查磁盘状态
            if (HmcStatus.DISK.CREATING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.UPDATING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.DELETING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.ASSIGNING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.UNASSIGNING.name().equals(vd.getStatus())) {
                logger.error("virtual disk {} 状态为{}，不能执行扩容操作!", vd.getDiskName(), vd.getStatus());
                return new BocloudResult(false, "虚拟磁盘" + diskName + "不能执行扩容操作");
            } else {
                vd.setStatus(HmcStatus.DISK.UPDATING.name());
                hmcVirtualDiskRepository.updateEntity(vd);
            }

            // 启动一个线程进行虚拟盘的创建
            taskExecutor.submit(() -> {

                String content = "在vios[" + vios.getName() + "]上扩容虚拟磁盘[" + diskName + "]到" + diskCapacity + "GB成功";
                try {
                    ResourceEvent event = new ResourceEvent(vios.getId(), ServerAction.CREATE.name(), "虚拟磁盘扩容成功",
                            context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                    // 扩容虚拟磁盘
                    BocloudResult result = volumeGroupDriver.updateVirtualDisk(vendor.getUuid(), vios.getUuid(),
                            vgs.get(0).getUuid(), diskCapacity, diskName);
                    if (result.isFailed()) {
                        logger.error("update virtual disk failed:{}", result);
                        vd.setStatus(HmcStatus.DISK.UPDATE_FAIL.name());
                        hmcVirtualDiskRepository.updateEntity(vd);
                        event = new ResourceEvent(vios.getId(), ServerAction.CREATE.name(), "虚拟磁盘扩容失败",
                                context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                        content = "在vios[" + vios.getName() + "]上扩容虚拟磁盘[" + diskName + "]失败:" + result.getMessage();
                        resourceEventRepository.save(event);
                        resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                        return;
                    }

                    // 从查询结果中获取虚拟磁盘的信息
                    VolumeGroupEntry vg = (VolumeGroupEntry) result.getData();
                    for (VirtualDisk virtualDisk : vg.getContent().getVolumeGroup().getVirtualDisks().getDisks()) {
                        if (diskName.equals(virtualDisk.getDiskName())) {
                            vd.setDiskCapacity(Double.parseDouble(virtualDisk.getDiskCapacity()));
                            vd.setDiskName(diskName);
                            vd.setVgId(vgs.get(0).getId());
                            vd.setUniqueDeviceId(virtualDisk.getUniqueDeviceID());
                            vd.setDiskLabel(virtualDisk.getDiskLabel());
                            vd.setStatus(HmcStatus.DISK.NORMAL.name());
                        }
                    }

                    // 更新虚拟磁盘信息到数据库
                    hmcVirtualDiskRepository.updateEntity(vd);

                    // 更新volume group的可用大小信息
                    HmcVolumeGroup volumeGroup = vgs.get(0);
                    volumeGroup.setAvailableSize(
                            Double.parseDouble(vg.getContent().getVolumeGroup().getAvailableSize()));
                    volumeGroup.setFreeSpace(Double.parseDouble(vg.getContent().getVolumeGroup().getFreeSpace()));
                    hmcVolumeGroupRepository.updateEntity(volumeGroup);

                    resourceEventRepository.save(event);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("扩容虚拟盘失败:", e);
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult(true, "扩容虚拟磁盘的任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("update virtual disk failed:", e);
            return new BocloudResult(false, "扩容虚拟磁盘失败");
        }
    }

    @Override
    public BocloudResult unAssignVd(HmcStorageUnassign params, RequestContext context) {
        Long viosId = params.getViosId();
        String path = HmcVolumeGroupServiceImpl.class.getSimpleName() + viosId;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                logger.warn("Get harmonyLock time out!");
                return new BocloudResult(false, "该vios上处于繁忙状态，请稍后重试");
            }

            Long serverId = params.getServerId();
            Long vendorId = params.getVendorId();
            Long diskId = params.getDiskId();
            if (null == serverId || null == vendorId || null == viosId || null == diskId) {
                logger.error("param {} error", params);
                return new BocloudResult(false, "参数异常");
            }

            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            if (null == vendor) {
                logger.error("vendor {} does not exist!", vendorId);
                return new BocloudResult(false, "ID为[" + vendorId + "]的云平台不存在");
            }
            HmcServer hmcServer = hmcServerRepository.getServerById(serverId);
            if (null == hmcServer) {
                logger.error("hmcServer {} does not exist!", serverId);
                return new BocloudResult(false, "ID为[" + serverId + "]的小机不存在");
            }

            HmcPartition vios = hmcPartitionRepository.getById(viosId);
            if (null == vios) {
                logger.error("vios {} does not exist!", viosId);
                return new BocloudResult(false, "ID为[" + viosId + "]的vios不存在");
            }
            HmcVirtualDisk vd = hmcVirtualDiskRepository.query(diskId);
            if (vd == null) {
                logger.error("vd {} does not exist!", diskId);
                return new BocloudResult(false, "id为[" + diskId + "]的虚拟磁盘不存在");
            }
            // 2019-08-21 : 将盘分配给逻辑分区,然后分区修改概要文件通过SCSI适配器使用上这个盘以后,如果分区不关机,该盘取消分配的时候会报错
            if (vd.getAssignPartitionId() == null) {
                logger.error("pd {} has not assign any partition!", vd.getDiskName());
                return new BocloudResult(false, "该卷尚未映射任何逻辑分区");
            }
            HmcPartition hmcPartition = hmcPartitionRepository.getById(vd.getAssignPartitionId());
            if (hmcPartition == null) {
                logger.error("lpar {} does not exist!", vd.getAssignPartitionId());
                return new BocloudResult(false, "ID为[" + vd.getAssignPartitionId() + "]的逻辑分区不存在");
            }
            if (HmcPartitionStatus.Running.getStatus().equals(hmcPartition.getStatus())
                    || HmcPartitionStatus.Open_Firmware.getStatus().equals(hmcPartition.getStatus())
                    || HmcPartitionStatus.Starting.getStatus().equals(hmcPartition.getStatus())
                    || HmcStatus.PARTITION.POWERON_RUNNING.getName().equals(hmcPartition.getStatus())
                    || HmcStatus.PARTITION.RESTART_RUNNING.getName().equals(hmcPartition.getStatus())) {
                logger.error("lpar {} is running!", hmcPartition.getName());
                return new BocloudResult(false, "请先将该卷已分配的逻辑分区[" + hmcPartition.getName() + "]关机");
            }
            // 检查磁盘状态
            if (HmcStatus.DISK.CREATING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.UPDATING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.DELETING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.ASSIGNING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.UNASSIGNING.name().equals(vd.getStatus())) {
                logger.error("virtual disk {} 状态为{}，不能执行取消分配操作!", vd.getDiskName(), vd.getStatus());
                return new BocloudResult(false, "虚拟磁盘" + vd.getDiskName() + "不能执行取消分配操作");
            }

            // TODO: 2020/8/31 这个极有可能V8也有同样的问题
            if ("V7".equals(vendor.getVersion())) {
                // 检查该vios是否存在这样的iscsi适配器：该适配器被分配了多个lv、pv、cd，如果存在则提示当前在不支持
                String multiAssignMsg = hmcDatabaseHelper.checkIscsiMultiAssign(viosId);
                if (StringUtils.isNotEmpty(multiAssignMsg)) {
                    return new BocloudResult(false, multiAssignMsg);
                }
            }

            vd.setStatus(HmcStatus.DISK.UNASSIGNING.name());
            hmcVirtualDiskRepository.updateEntity(vd);


            // 启动一个线程进行虚拟盘的取消分配
            taskExecutor.submit(() -> {
                String content = "在vios[" + vios.getName() + "]上取消分配[" + vd.getDiskName() + "]成功";
                try {
                    ResourceEvent event = new ResourceEvent(vios.getId(), ServerAction.UPDATE.name(), "虚拟取消分配成功",
                            context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                    BocloudResult unAssignResult = volumeGroupDriver.unAssign(vendor.getUuid(), hmcServer.getUuid(),
                            vios.getUuid(), vd.getDiskName(), false);
                    if (unAssignResult.isFailed()) {
                        logger.error("取消分配虚拟磁盘{}失败:{}", vd.getDiskName(), unAssignResult);
                        vd.setStatus(HmcStatus.DISK.UNASSIGN_FAIL.name());
                        hmcVirtualDiskRepository.updateEntity(vd);
                        event = new ResourceEvent(vios.getId(), ServerAction.UPDATE.name(), "取消分配虚拟磁盘失败",
                                context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                        content = "在vios[" + vios.getName() + "]上取消分配虚拟磁盘[" + vd.getDiskName() + "]失败:"
                                + unAssignResult.getMessage();
                        resourceEventRepository.save(event);
                        resourceEventPublisher.send(new OperateResult(unAssignResult.isSuccess(), content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                        return;
                    }
                    // update vg assign info
                    vd.setAssignPartitionId(null);
                    vd.setAssignSlotId(null);
                    vd.setViosSlotId(null);
                    vd.setStatus(HmcStatus.DISK.NORMAL.name());
                    hmcVirtualDiskRepository.updateEntity(vd);
                    // 取消分配后，更新vios的所有SCSI数据
                    VirtualIOServerEntry virtualIOServerEntry = (VirtualIOServerEntry) unAssignResult.getData();
                    hmcPartitionService.updateVirtualScsiAdapterForVios(vios,
                            virtualIOServerEntry.getContent().getVirtualIOServer().getVirtualSCSIMappings());
                    resourceEventRepository.save(event);
                    resourceEventPublisher.send(new OperateResult(true, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("取消分配虚拟盘失败:", e);
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult(true, "取消分配虚拟磁盘" + vd.getDiskName() + "的任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("unassign virtual disk failed:", e);
            return new BocloudResult(false, "取消分配磁盘失败");
        }
    }

    @Override
    public BocloudResult unAssignPd(HmcStorageUnassign params, RequestContext context) {
        Long viosId = params.getViosId();
        String path = HmcVolumeGroupServiceImpl.class.getSimpleName() + viosId;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                logger.warn("Get harmonyLock time out!");
                return new BocloudResult(false, "该vios上处于繁忙状态，请稍后重试");
            }

            Long serverId = params.getServerId();
            Long vendorId = params.getVendorId();
            Long volumeId = params.getVolumeId();
            if (null == serverId || null == vendorId || null == viosId || null == volumeId) {
                logger.error("param {} error", params);
                return new BocloudResult(false, "参数异常");
            }

            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            if (null == vendor) {
                logger.error("vendor {} does not exist!", vendorId);
                return new BocloudResult(false, "ID为[" + vendorId + "]的云平台不存在");
            }
            HmcServer hmcServer = hmcServerRepository.getServerById(serverId);
            if (null == hmcServer) {
                logger.error("hmcServer {} does not exist!", serverId);
                return new BocloudResult(false, "ID为[" + serverId + "]的小机不存在");
            }

            HmcPartition vios = hmcPartitionRepository.getById(viosId);
            if (null == vios) {
                logger.error("vios {} does not exist!", viosId);
                return new BocloudResult(false, "ID为[" + viosId + "]的vios不存在");
            }
            HmcPhysicalDisk pd = hmcPhysicalDiskRepository.query(volumeId);
            if (pd == null) {
                logger.error("pd {} does not exist!", volumeId);
                return new BocloudResult(false, "ID为[" + volumeId + "]的物理卷不存在");
            }
            // 2019-08-21 : 将盘分配给逻辑分区,然后分区修改概要文件通过SCSI适配器使用上这个盘以后,如果分区不关机,该盘取消分配的时候会报错
            if (pd.getAssignPartitionId() == null) {
                logger.error("pd {} has not assign any partition!", pd.getVolumeName());
                return new BocloudResult(false, "该卷尚未映射任何逻辑分区");
            }
            HmcPartition hmcPartition = hmcPartitionRepository.getById(pd.getAssignPartitionId());
            if (hmcPartition == null) {
                logger.error("lpar {} does not exist!", pd.getAssignPartitionId());
                return new BocloudResult(false, "ID为[" + pd.getAssignPartitionId() + "]的逻辑分区不存在");
            }
            if (HmcPartitionStatus.Running.getStatus().equals(hmcPartition.getStatus())
                    || HmcPartitionStatus.Open_Firmware.getStatus().equals(hmcPartition.getStatus())
                    || HmcPartitionStatus.Starting.getStatus().equals(hmcPartition.getStatus())
                    || HmcStatus.PARTITION.POWERON_RUNNING.getName().equals(hmcPartition.getStatus())
                    || HmcStatus.PARTITION.RESTART_RUNNING.getName().equals(hmcPartition.getStatus())) {
                logger.error("lpar {} is running!", hmcPartition.getName());
                return new BocloudResult(false, "请先将该卷已分配的逻辑分区[" + hmcPartition.getName() + "]关机");
            }
            // TODO: 2020/8/31 这个极有可能V8也有同样的问题
            if ("V7".equals(vendor.getVersion())) {
                // 检查该vios是否存在这样的iscsi适配器：该适配器被分配了多个lv、pv、cd，如果存在则提示当前在不支持
                String multiAssignMsg = hmcDatabaseHelper.checkIscsiMultiAssign(viosId);
                if (StringUtils.isNotEmpty(multiAssignMsg)) {
                    return new BocloudResult(false, multiAssignMsg);
                }
            }
            // 启动一个线程进行物理卷的取消分配
            taskExecutor.submit(() -> {

                String content = "在vios[" + vios.getName() + "]上取消分配物理卷[" + pd.getVolumeName() + "]成功";
                try {
                    ResourceEvent event = new ResourceEvent(vios.getId(), ServerAction.UPDATE.name(), "虚拟取消分配成功",
                            context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                    Result unAssignResult = volumeGroupDriver.unAssign(vendor.getUuid(), hmcServer.getUuid(),
                            vios.getUuid(), pd.getVolumeName(), true);
                    if (unAssignResult.isFailed()) {
                        logger.error("取消分配物理卷{}失败:{}", pd.getVolumeName(), unAssignResult);
                        event = new ResourceEvent(vios.getId(), ServerAction.UPDATE.name(), "取消分配物理卷失败",
                                context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                        content = "在vios[" + vios.getName() + "]上取消分配物理卷[" + pd.getVolumeName() + "]失败:"
                                + unAssignResult.getMessage();
                        resourceEventRepository.save(event);
                        resourceEventPublisher.send(new OperateResult(unAssignResult.isSuccess(), content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                        return;
                    }
                    // update vg assign info
                    pd.setAssignPartitionId(null);
                    pd.setAssignSlotId(null);
                    pd.setViosSlotId(null);
                    hmcPhysicalDiskRepository.updateEntity(pd);
                    resourceEventRepository.save(event);
                    resourceEventPublisher.send(new OperateResult(true, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("取消分配物理卷失败:", e);
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult(true, "取消分配物理卷" + pd.getVolumeName() + "的任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("unassign physical disk failed:", e);
            return new BocloudResult(false, "取消分配物理卷失败");
        }
    }

    @Override
    public BocloudResult deleteVd(HmcVolumeGroupParams params, RequestContext context) {
        Long viosId = params.getViosId();
        String path = HmcVolumeGroupServiceImpl.class.getSimpleName() + viosId;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                logger.warn("Get harmonyLock time out!");
                return new BocloudResult(false, "该vios上处于繁忙状态，请稍后重试");
            }

            Long serverId = params.getServerId();
            Long vendorId = params.getVendorId();

            String groupName = params.getGroupName();
            String diskName = params.getDiskName();
            Double diskCapacity = params.getDiskCapacity();
            if (null == serverId || null == vendorId || null == viosId || null == groupName || null == diskName
                    || null == diskCapacity) {
                logger.error("param {} error", params);
                return new BocloudResult(false, "参数异常");
            }

            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            if (null == vendor) {
                logger.error("vendor {} does not exist!", vendorId);
                return new BocloudResult(false, "ID为[" + vendorId + "]的云平台不存在");
            }
            HmcServer hmcServer = hmcServerRepository.getServerById(serverId);
            if (null == hmcServer) {
                logger.error("hmcServer {} does not exist!", serverId);
                return new BocloudResult(false, "ID为[" + serverId + "]的小机不存在");
            }

            HmcPartition vios = hmcPartitionRepository.getById(viosId);
            if (null == vios) {
                logger.error("vios {} does not exist!", viosId);
                return new BocloudResult(false, "ID为[" + viosId + "]的vios不存在");
            }
            List<HmcVolumeGroup> vgs = hmcVolumeGroupRepository.query(vios.getId(), groupName);
            if (vgs.size() != 1) {
                logger.error("vg {} does not exist!", groupName);
                return new BocloudResult(false, "名称为[" + groupName + "]的vg不存在");
            }

            HmcVirtualDisk vd = hmcVirtualDiskRepository.query(diskName, viosId, vgs.get(0).getId());
            if (null == vd) {
                logger.error("virtual disk {} does not exist!", diskName);
                return new BocloudResult(false, "名称为[" + diskName + "]的虚拟磁盘不存在");
            }

            // 检查磁盘状态
            if (HmcStatus.DISK.CREATING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.UPDATING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.DELETING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.ASSIGNING.name().equals(vd.getStatus())
                    || HmcStatus.DISK.UNASSIGNING.name().equals(vd.getStatus())) {
                logger.error("virtual disk {} 状态为{}，不能执行分配操作!", vd.getDiskName(), vd.getStatus());
                return new BocloudResult(false, "虚拟磁盘" + diskName + "不能执行分配操作");
            } else {
                vd.setStatus(HmcStatus.DISK.DELETING.name());
                hmcVirtualDiskRepository.updateEntity(vd);
            }

            // 启动一个线程进行虚拟盘的删除
            taskExecutor.submit(() -> {

                String content = "在vios[" + vios.getName() + "]上删除虚拟磁盘[" + diskName + "]成功";
                try {
                    ResourceEvent event = new ResourceEvent(vios.getId(), ServerAction.DELETE.name(), "虚拟磁盘删除成功",
                            context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                    Result result = null;
                    // 从hmc上取消分配虚拟磁盘
                    if (vd.getAssignPartitionId() != null) {
                        result = volumeGroupDriver.unAssign(vendor.getUuid(), hmcServer.getUuid(), vios.getUuid(),
                                diskName, false);
                        if (result.isFailed()) {
                            logger.error("delete virtual disk failed: unAssign fail {}", result);
                            vd.setStatus(HmcStatus.DISK.DELETE_FAIL.name());
                            hmcVirtualDiskRepository.updateEntity(vd);
                            event = new ResourceEvent(vios.getId(), ServerAction.DELETE.name(), "虚拟磁盘删除失败",
                                    context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                            content = "在vios[" + vios.getName() + "]上删除虚拟磁盘[" + diskName + "]失败, 取消分配失败:"
                                    + result.getMessage();
                            resourceEventRepository.save(event);
                            resourceEventPublisher.send(new OperateResult(false, content, operate,
                                    MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                            return;
                        }
                    }
                    // 从hmc上删除虚拟磁盘
                    result = volumeGroupDriver.deleteVirtualDisk(vendor.getUuid(), vios.getUuid(),
                            vgs.get(0).getUuid(), diskName);
                    if (result.isFailed()) {
                        logger.error("delete virtual disk failed: {}", result);
                        vd.setStatus(HmcStatus.DISK.DELETE_FAIL.name());
                        hmcVirtualDiskRepository.updateEntity(vd);
                        event = new ResourceEvent(vios.getId(), ServerAction.DELETE.name(), "虚拟磁盘删除失败",
                                context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                        content = "在vios[" + vios.getName() + "]上删除虚拟磁盘[" + diskName + "]失败:" + result.getMessage();
                        resourceEventRepository.save(event);
                        resourceEventPublisher.send(new OperateResult(false, content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                        return;
                    }
                    // 从数据库中删除虚拟磁盘
                    boolean success = hmcVirtualDiskRepository.delete(vgs.get(0).getId(), diskName);
                    if (!success) {
                        logger.error("delete virtual disk from database failed", success);
                        vd.setStatus(HmcStatus.DISK.DELETE_FAIL.name());
                        hmcVirtualDiskRepository.updateEntity(vd);
                        event = new ResourceEvent(vios.getId(), ServerAction.DELETE.name(), "虚拟磁盘删除失败",
                                context.getTarget(), new Date(), "HMC", vendorId, context.getCatalog());
                        content = "在vios[" + vios.getName() + "]上删除虚拟磁盘[" + diskName + "]失败, 删除数据库数据失败.";
                        resourceEventRepository.save(event);
                        resourceEventPublisher.send(new OperateResult(false, content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                        return;
                    }

                    // update vg availableSize and freeSpace
                    HmcVolumeGroup volumeGroup = vgs.get(0);
                    volumeGroup.setAvailableSize(volumeGroup.getAvailableSize() + diskCapacity);
                    volumeGroup.setFreeSpace(volumeGroup.getFreeSpace() + diskCapacity);
                    hmcVolumeGroupRepository.updateEntity(volumeGroup);

                    resourceEventRepository.save(event);
                    resourceEventPublisher.send(new OperateResult(true, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("删除虚拟盘失败:", e);
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult(true, "删除虚拟磁盘的任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("delete virtual disk failed:", e);
            return new BocloudResult(false, "删除失败");
        }
    }

    @Override
    public BocloudResult createVG(HmcVolumeGroupCreateParams params, RequestContext context) {
        try {
            Long viosId = params.getViosId();
            if (viosId == null) {
                return new BocloudResult(false, "需要参数viosId");
            }
            HmcPartition vios = hmcPartitionRepository.getById(viosId);
            if (vios == null || vios.getDeleted()) {
                return new BocloudResult(false, "未找到ID为" + viosId + "的VIOS");
            }
            if (!HmcPartitionType.VIOS.getType().equals(vios.getPartitionType())) {
                return new BocloudResult(false, "该ID对应的分区不是VIOS");
            }

            HmcServer server = hmcServerRepository.getServerById(vios.getServerId());
            if (server == null || server.getDeleted()) {
                return new BocloudResult(false, "未找到ID为" + vios.getServerId() + "的主机");
            }

            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            if (vendor == null || vendor.getDeleted()) {
                return new BocloudResult(false, "未找到ID为" + server.getVendorId() + "的平台");
            }

            String vgName = params.getVgName();
            if (StringUtils.isEmpty(vgName)) {
                return new BocloudResult(false, "需要参数vgName");
            }
            List<HmcVolumeGroup> vgByName = hmcVolumeGroupRepository.query(viosId, vgName);
            if (vgByName != null && vgByName.size() > 0) {
                return new BocloudResult(false, "名称为" + vgName + "的存储池已经存在");
            }

            JSONArray pdIds = JSON.parseArray(params.getPdIds());
            if (pdIds == null || pdIds.size() == 0) {
                return new BocloudResult(false, "需要参数pdIds");
            }
            List<HmcPhysicalDisk> pds = new ArrayList<>();
            for (int i = 0; i < pdIds.size(); i++) {
                Long pdId = pdIds.getLong(i);
                HmcPhysicalDisk pd = hmcPhysicalDiskRepository.query(pdId);
                if (pd == null) {
                    return new BocloudResult(false, "未找到ID为" + pdId + "的物理磁盘");
                }
                if (pd.getVgId() != null) {
                    return new BocloudResult(false, "ID为" + pdId + "的物理磁盘已经被其他存储池使用");
                }
                pds.add(pd);
            }

            // 组装要传递给driver的参数
            VolumeGroup vg = new VolumeGroup();
            vg.setGroupName(vgName);

            PhysicalVolumes pvs = new PhysicalVolumes();
            pvs.setPhysicalVolumeList(new ArrayList<>());
            for (HmcPhysicalDisk pd : pds) {
                PhysicalVolume pv = new PhysicalVolume();
                pv.setUniqueDeviceId(pd.getUniqueDeviceId());
                pv.setLocationCode(pd.getLocationCode());
                pv.setReservePolicy(pd.getReservePolicy());
                pv.setReservePolicyAlgorithm(pd.getReservePolicyAlgorithm());
                pv.setAvailableForUsage(pd.getAvailable() == null ? "false" : pd.getAvailable().toString());
                pv.setVolumeName(pd.getVolumeName());
                pv.setVolumeState(pd.getVolumeState());
                pvs.getPhysicalVolumeList().add(pv);
            }
            vg.setPhysicalVolumes(pvs);

            taskExecutor.submit(() -> {
                OperateResult operateResult = new OperateResult(true, "", operate,
                        MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context);
                try {
                    BocloudResult bocloudResult = volumeGroupDriver.createVolumeGroup(vendor.getUuid(), vios.getUuid(),
                            vg);
                    if (bocloudResult.isFailed()) {
                        operateResult.setSuccess(false);
                        operateResult.setMessage("创建存储池[" + vgName + "]失败：" + bocloudResult.getMessage());
                        resourceEventPublisher.send(operateResult);
                        return;
                    }

                    VolumeGroupEntry vgEntry = (VolumeGroupEntry) bocloudResult.getData();

                    HmcVolumeGroup vgDB = new HmcVolumeGroup();
                    vgDB.setAvailableSize(Double.parseDouble(vgEntry.getContent().getVolumeGroup().getAvailableSize()));
                    vgDB.setFreeSpace(Double.parseDouble(vgEntry.getContent().getVolumeGroup().getFreeSpace()));
                    vgDB.setGroupCapacity(Double.parseDouble(vgEntry.getContent().getVolumeGroup().getGroupCapacity()));
                    vgDB.setGroupName(vgEntry.getContent().getVolumeGroup().getGroupName());
                    vgDB.setViosId(vios.getId());
                    vgDB.setGroupSerialId(vgEntry.getContent().getVolumeGroup().getGroupSerialID());
                    vgDB.setMaxLogicalVolumes(
                            Long.parseLong(vgEntry.getContent().getVolumeGroup().getMaximumLogicalVolumes()));
                    vgDB.setUuid(vgEntry.getContent().getVolumeGroup().getMetadata().getAtom().getAtomId());
                    hmcVolumeGroupRepository.save(vgDB);

                    for (HmcPhysicalDisk pd : pds) {
                        HmcPhysicalDisk pDisk = hmcPhysicalDiskRepository.query(pd.getId());
                        pDisk.setVgId(vgDB.getId());
                        hmcPhysicalDiskRepository.updateEntity(pDisk);
                    }

                    operateResult.setSuccess(true);
                    operateResult.setMessage("创建存储池[" + vgName + "]成功");
                    resourceEventPublisher.send(operateResult);
                } catch (Exception e) {
                    operateResult.setSuccess(false);
                    operateResult.setMessage("创建存储池[" + vgName + "]失败：" + e.getMessage());
                    resourceEventPublisher.send(operateResult);
                }
            });
            return new BocloudResult(true, "任务已经下发，正在执行...");
        } catch (Exception e) {
            logger.error("创建存储池异常：", e);
            return new BocloudResult(false, "创建存储池异常：" + e.getMessage());
        }
    }

    @Override
    public BocloudResult removeVG(Long vgId, RequestContext context) {
        try {
            if (vgId == null) {
                return new BocloudResult(false, "需要参数id");
            }
            HmcVolumeGroup vg = hmcVolumeGroupRepository.query(vgId);
            if (vg == null) {
                return new BocloudResult(false, "未找到ID为" + vg + "的存储池");
            }

            HmcPartition vios = hmcPartitionRepository.getById(vg.getViosId());
            if (vios == null || vios.getDeleted()) {
                return new BocloudResult(false, "未找到ID为" + vg.getViosId() + "的VIOS");
            }

            HmcServer server = hmcServerRepository.getServerById(vios.getServerId());
            if (server == null || server.getDeleted()) {
                return new BocloudResult(false, "未找到ID为" + vios.getServerId() + "的主机");
            }

            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            if (vendor == null || vendor.getDeleted()) {
                return new BocloudResult(false, "未找到ID为" + server.getVendorId() + "的平台");
            }

            taskExecutor.submit(() -> {
                OperateResult operateResult = new OperateResult(true, "", operate,
                        MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context);
                try {
                    BocloudResult bocloudResult = volumeGroupDriver.deleteVolumeGroup(vendor.getUuid(), vios.getUuid(),
                            vg.getUuid());
                    if (bocloudResult.isFailed()) {
                        operateResult.setSuccess(false);
                        operateResult.setMessage("删除存储池[" + vg.getGroupName() + "]失败：" + bocloudResult.getMessage());
                        resourceEventPublisher.send(operateResult);
                        return;
                    }

                    List<HmcPhysicalDisk> pds = hmcPhysicalDiskRepository.query(vios.getId(), null);
                    for (HmcPhysicalDisk pd : pds) {
                        if (pd.getVgId() != null && pd.getVgId().equals(vg.getId())) {
                            pd.setVgId(null);
                            hmcPhysicalDiskRepository.updateEntity(pd);
                        }
                    }

                    List<HmcVirtualDisk> vds = hmcVirtualDiskRepository.queryByVgIdViosId(vg.getId(), vios.getId());
                    for (HmcVirtualDisk vd : vds) {
                        hmcVirtualDiskRepository.delete(vd);
                    }

                    hmcVolumeGroupRepository.delete(vg);

                    operateResult.setSuccess(true);
                    operateResult.setMessage("删除存储池[" + vg.getGroupName() + "]成功");
                    resourceEventPublisher.send(operateResult);
                } catch (Exception e) {
                    operateResult.setSuccess(false);
                    operateResult.setMessage("删除存储池[" + vg.getGroupName() + "]失败：" + e.getMessage());
                    resourceEventPublisher.send(operateResult);
                }
            });
            return new BocloudResult(true, "任务已经下发，正在执行...");
        } catch (Exception e) {
            logger.error("创建存储池异常：", e);
            return new BocloudResult(false, "创建存储池异常：" + e.getMessage());
        }
    }
}
