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.HmcCommonDriver;
import com.bocloud.cmp.driver.hmc.HmcPartitionDriver;
import com.bocloud.cmp.driver.hmc.HmcVirtualFibreChannelMappingDriver;
import com.bocloud.cmp.driver.hmc.HmcVirtualNetworkDriver;
import com.bocloud.cmp.entity.enums.HmcPartitionType;
import com.bocloud.cmp.model.NotifyMessage;
import com.bocloud.cmp.model.hmc.HmcPartitionModel;
import com.bocloud.cmp.model.hmc.sdk.module.*;
import com.bocloud.common.model.*;
import com.bocloud.common.model.OperateResult.OperateCategory;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.common.utils.IDFactory;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.common.Constant;
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.common.User;
import com.bocloud.ims.entity.resource.CloudServer;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.ResourceEvent;
import com.bocloud.ims.entity.resource.Server;
import com.bocloud.ims.entity.resource.hmc.*;
import com.bocloud.ims.entity.resource.hmc.params.*;
import com.bocloud.ims.interfaces.resource.hmc.HmcNimService;
import com.bocloud.ims.interfaces.resource.hmc.HmcPartitionService;
import com.bocloud.ims.interfaces.resource.hmc.HmcVirtualFibreChannelMappingService;
import com.bocloud.ims.interfaces.resource.hmc.HmcVolumeGroupService;
import com.bocloud.ims.repository.resource.CloudServerRepository;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.ResourceEventRepository;
import com.bocloud.ims.repository.resource.ServerRepository;
import com.bocloud.ims.repository.resource.hmc.*;
import com.bocloud.ims.service.builder.HmcServerBuilder;
import com.bocloud.ims.service.internal.SmsUserService;
import com.bocloud.ims.service.internal.worker.RequestWorkerService;
import com.bocloud.ims.service.transportor.HmcTransportor;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service("hmcPartitionService")
public class HmcPartitionServiceImpl implements HmcPartitionService {
    private static final Logger logger = LoggerFactory.getLogger(HmcPartitionServiceImpl.class);
    private static OperateCategory operateCategory = OperateCategory.ResourceEvent;
    private static final String OPERATE_RESULT_TYPE = "hmc.lpar.refresh";
    private static final String NOT_EXIST = "REST000B The URL presented to the Management Console REST Web Services is not valid.";

    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private RequestWorkerService requestWorker;
    @Autowired
    private HmcCommonDriver commonDriver;
    @Autowired
    private HmcPartitionDriver partitionDriver;
    @Autowired
    private HmcVirtualFibreChannelMappingDriver virtualFibreChannelMappingDriver;
    @Autowired
    private HmcPartitionRepository hmcPartitionRepository;
    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private HmcServerBuilder hmcServerBuilder;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private HmcServerRepository hmcServerRepository;
    @Autowired
    private HmcPhysicalEthernetAdapterRepository hmcPhysicalEthernetAdapterRepository;
    @Autowired
    private HmcShareEthernetAdapterRepository hmcShareEthernetAdapterRepository;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private HmcDatabaseHelper hmcDatabaseHelper;
    @Autowired
    private ResourceEventRepository resourceEventRepository;
    @Autowired
    private HmcProfileRepository hmcProfileRepository;
    @Autowired
    private HmcPartitionScsiAdapterRepository hmcPartitionScsiAdapterRepository;
    @Autowired
    private HmcVolumeGroupService hmcVolumeGroupService;
    @Autowired
    private HmcVolumeGroupRepository hmcVolumeGroupRepository;
    @Autowired
    private SmsUserService smsUserService;
    @Autowired
    private HmcNimService nimService;
    @Autowired
    private HmcPhysicalFibreChannelRepository hmcPhysicalFibreChannelRepository;
    @Autowired
    private HmcVirtualFibreChannelMappingRepository hmcVirtualFibreChannelMappingRepository;
    @Autowired
    private HmcPartitionVfcAdapterRepository hmcPartitionVfcAdapterRepository;
    @Autowired
    private HmcPartitionNetworkAdapterRepository hmcPartitionNetworkAdapterRepository;
    @Autowired
    private HmcVirtualSwitchRepository hmcVirtualSwitchRepository;
    @Autowired
    private HmcVirtualNetworkDriver hmcVirtualNetworkDriver;
    @Autowired
    private HmcVirtualFibreChannelMappingService hmcVirtualFibreChannelMappingService;
    @Autowired
    private HmcProfileFibreAdapterRepository hmcProfileFibreAdapterRepository;
    @Autowired
    private CloudServerRepository cloudServerRepository;
    @Autowired
    private ServerRepository serverRepository;
    @Autowired
    private HmcTransportor hmcTransportor;
    @Autowired
    private HmcProfileServiceImpl hmcProfileService;
    @Autowired
    private HmcPhysicalDiskRepository hmcPhysicalDiskRepository;
    @Autowired
    private HmcPartitionMemoryRepository hmcPartitionMemoryRepository;
    @Autowired
    private HmcPartitionProcessorRepository hmcPartitionProcessorRepository;
    @Autowired
    private HmcPartitionIoRepository hmcPartitionIoRepository;

    @Override
    public BocloudResult updateLpar(Long lparId, RequestContext context) {
        try {
            HmcPartition lpar = hmcPartitionRepository.getById(lparId);
            HmcServer server = hmcServerRepository.getServerById(lpar.getServerId());
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            // 创建虚拟磁盘
            BocloudResult result = partitionDriver.getPartitionAttribute(vendor.getUuid(), lpar.getUuid(), false);
            if (result.isSuccess()) {
                LogicalPartitionEntry entry = (LogicalPartitionEntry) result.getData();
                boolean updateResult = hmcDatabaseHelper.updatePartition(lpar, entry.getContent().getLogicalPartition(),
                        null, true, context.getTarget());
                return new BocloudResult(updateResult, updateResult ? "更新逻辑分区成功" : "更新逻辑分区失败");
            } else {
                logger.error("get partition from HMC failure, {}!", result);
                return new BocloudResult(false, "更新逻辑分区失败");
            }
        } catch (Exception e) {
            logger.error("update logical partiton error:", e);
            return new BocloudResult(false, "更新逻辑分区失败");
        }
    }

    @Override
    public BocloudResult<GridBean<Long>> list(Pager pager, RequestContext context) {
        GridBean gridBean = null;
        try {
            int page = pager.getPage();
            int rows = pager.getRows();
            List<Param> params = pager.getParams();
            Map<String, String> sorter = pager.getSorter();
            boolean simple = pager.getSimple();

            if (null == params) {
                return new BocloudResult(false, "参数格式错误");
            }
            Long vendorId = null;
            String serverName = null;
            for (Param param : params) {
                Map<String, Object> paramMap = param.getParam();
                if (paramMap.containsKey("vendorId")) {
                    vendorId = Long.valueOf(paramMap.get("vendorId").toString());
                    paramMap.remove("vendorId");
                }
                if (paramMap.containsKey("serverName")) {
                    serverName = paramMap.get("serverName").toString();
                    paramMap.remove("serverName");
                }
            }
            if (null == sorter) {
                sorter = Maps.newHashMap();
            }
            sorter.put("gmtCreate", Common.ONE);

            if (context.getTenant() == 0) {// 管理端查询的所有记录
                gridBean = this.getGridBean(page, rows, params, vendorId, serverName, simple, sorter, null, null);
            } else {
                BocloudResult<User> result = smsUserService.detail(context.getTarget());
                if (result.isFailed()) {
                    return new BocloudResult(false, result.getMessage());
                }
                if (null == result.getData()) {
                    logger.warn("context does not exists");
                    return new BocloudResult(false, "用户存在问题，请联系管理员");
                }
                User loginUser = result.getData();
                if (RequestContext.Catalog.Tenant == context.getCatalog()) {// 租户管理员查询所属租户的所有记录
                    gridBean = this.getGridBean(page, rows, params, vendorId, serverName, simple, sorter,
                            context.getTenant(), null);
                } else {
                    gridBean = this.getGridBean(page, rows, params, vendorId, serverName, simple, sorter, null,
                            context.getTarget());
                }
            }

            return new BocloudResult(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("Query partition list fail:", e);
            return new BocloudResult(false, "查询失败");
        }
    }

    private GridBean getGridBean(int page, int rows, List<Param> params, Long vendorId, String serverName,
                                 boolean simple, Map<String, String> sorter, Long tenantId, Long userId) {
        GridBean gridBean = null;
        int total = this.hmcPartitionRepository.count(params, vendorId, serverName, tenantId, userId);
        if (simple) {
            List<SimpleBean> beans = this.hmcPartitionRepository.list(params, sorter, tenantId, userId);
            gridBean = new GridBean(1, 1, total, beans);
        } else {
            List<HmcPartition> list = this.hmcPartitionRepository.list(page, rows, params, sorter, vendorId, serverName,
                    tenantId, userId);
            for (HmcPartition partition : list) {
                // 获取活动概要文件的名称, 分区激活过，这个活动概要文件是这个激活的概要文件，否则是默认概要文件。
                HmcProfile profile = this.hmcProfileRepository.getActiveProfile(partition.getId());
                if (null != profile) {
                    partition.setProfileName(profile.getName());
                } else {
                    HmcProfile defaulProfile = this.hmcProfileRepository.getDefaultProfile(partition.getId());
                    if (null != defaulProfile) {
                        partition.setProfileName(defaulProfile.getName());
                    }
                }
            }
            gridBean = GridHelper.getBean(page, rows, total, list);
        }
        return gridBean;
    }

    @Override
    public BocloudResult<HmcPartition> detail(Long id) {
        try {
            // 分区
            HmcPartition partition = this.hmcPartitionRepository.getById(id);
            if (partition == null) {
                logger.warn("HMC partition does not exist!");
                return new BocloudResult(false, null, "分区不存在");
            }

            // 服务器
            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, "云平台不存在!");
            }

            if (Objects.equals(HmcPartitionType.VIOS.getType(), partition.getPartitionType())) {
                partition.setHmcPartitionScsiAdapters(
                        hmcPartitionScsiAdapterRepository.queryByPartitionId(partition.getId()));
                partition.setHmcVirtualFibreChannelMappings(
                        hmcVirtualFibreChannelMappingRepository.listByViosId(partition.getId()));
                partition.setHmcPartitionNetworkAdapters(
                        hmcPartitionNetworkAdapterRepository.getByPartitionId(partition.getId()));
            } else {
                partition.setHmcPartitionScsiAdapters(
                        hmcPartitionScsiAdapterRepository.queryByPartitionId(partition.getId()));
                partition.setHmcVirtualFibreChannelMappings(
                        hmcVirtualFibreChannelMappingRepository.listByPartitionId(partition.getId()));
                partition.setHmcPartitionNetworkAdapters(
                        hmcPartitionNetworkAdapterRepository.getByPartitionId(partition.getId()));
            }
            partition.setHmcPartitionProcessor(hmcPartitionProcessorRepository.getByPartitionId(partition.getId()));
            partition.setHmcPartitionMemory(hmcPartitionMemoryRepository.getByPartitionId(partition.getId()));
            partition.setHmcPartitionIos(hmcPartitionIoRepository.listByPartitionId(partition.getId()));

            HmcProfile profile = this.hmcProfileRepository.getActiveProfile(partition.getId());
            if (null != profile) {
                partition.setProfileName(profile.getName());
            }

            return new BocloudResult(true, partition, "查询成功");
        } catch (Exception e) {
            logger.error("Query HMC partition detail fail:", e);
            return new BocloudResult(false, "查询失败", null, null);
        }
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void updateVirtualFibreChannelMappingForLpar(HmcPartition lpar, Long vendorId) {
        // 云平台
        CloudVendor vendor = cloudVendorRepository.query(vendorId);
        if (null == vendor) {
            throw new RuntimeException("未找到平台");
        }
        BocloudResult bocloudResult = virtualFibreChannelMappingDriver.getVfcFromPartition(vendor.getUuid(),
                lpar.getUuid());
        if (bocloudResult.isFailed()) {
            logger.info("获取vfc信息失败：" + bocloudResult.getErrorMsg());
        }
        // 获取逻辑分区原始的光纤通道mapping
        List<HmcPartitionVfcAdapter> hmcMappings = hmcPartitionVfcAdapterRepository.listByPartitionId(lpar.getId());
        Map<Integer, HmcPartitionVfcAdapter> oldFcMap = Maps.newHashMap();
        for (HmcPartitionVfcAdapter mapping : hmcMappings) {
            oldFcMap.put(mapping.getClientPartitionSlot(), mapping);
        }
        // 开始更新或保存
        LogicalPartitionVfcResponse logicalPartitionVfcResponse = (LogicalPartitionVfcResponse) bocloudResult.getData();
        if (logicalPartitionVfcResponse == null || logicalPartitionVfcResponse.getEntries() == null
                || logicalPartitionVfcResponse.getEntries().size() == 0) {
            logger.info("逻辑分区" + lpar.getName() + "没有虚拟vfc适配器");
            for (HmcPartitionVfcAdapter hmcPartitionVfcAdapter : oldFcMap.values()) {
                hmcPartitionVfcAdapterRepository.delete(hmcPartitionVfcAdapter);
            }
        } else {
            lpar.setHmcVirtualFibreChannelMappings(new ArrayList<>());
            for (LogicalPartitionVfcEntry logicalPartitionVfcEntry : logicalPartitionVfcResponse.getEntries()) {
                if (logicalPartitionVfcEntry.getContent().getVirtualFibreChannelClientAdapter() != null) {
                    VirtualFibreChannelClientAdapter mappingFromDriver = logicalPartitionVfcEntry.getContent()
                            .getVirtualFibreChannelClientAdapter();
                    int partitionSlotNo = Integer.parseInt(mappingFromDriver.getVirtualSlotNumber()); // 获取该映射在逻辑分区上的槽号
                    int partitionHmcId = Integer.parseInt(mappingFromDriver.getLocalPartitionID()); // 获取该逻辑分区在hmc中的id
                    int viosSlotNo = Integer.parseInt(mappingFromDriver.getConnectingVirtualSlotNumber()); // 获取该映射在vios上的槽号
                    int viosHmcId = Integer.parseInt(mappingFromDriver.getConnectingPartitionID()); // 获取vios在hmc中的id
                    HmcPartitionVfcAdapter mappingForDB = oldFcMap.get(partitionSlotNo) == null
                            ? new HmcPartitionVfcAdapter()
                            : oldFcMap.get(partitionSlotNo); // 创建要最终执行保存的对象
                    // 先把逻辑分区这一端能赋值的先赋值
                    mappingForDB.setCmpPartitionId(lpar.getId());
                    mappingForDB.setClientPartitionName(lpar.getName());
                    mappingForDB.setClientPartitionId(partitionHmcId);
                    mappingForDB.setClientPartitionSlot(partitionSlotNo);
                    mappingForDB.setClientViredOn(BooleanUtils.toBoolean(mappingFromDriver.getVariedOn()));
                    mappingForDB.setClientRequired(BooleanUtils.toBoolean(mappingFromDriver.getRequiredAdapter()));
                    mappingForDB.setClientWwpns(mappingFromDriver.getWwpns());
                    mappingForDB.setServerViosId(viosHmcId);
                    mappingForDB.setServerViosSlot(viosSlotNo);
                    HmcServer hmcServer = hmcServerRepository.getServerById(lpar.getServerId());
                    HmcPartition vios = hmcPartitionRepository.getByHmcPartitionId(viosHmcId, hmcServer.getId());
                    if (vios != null && !vios.getDeleted()) {
                        // 更新下vios的vfc中partition相关信息
                        HmcVirtualFibreChannelMapping mappingOfVios = hmcVirtualFibreChannelMappingRepository
                                .queryMappingByViosIdAndSlot(vios.getId(), viosSlotNo);
                        if (mappingOfVios != null && mappingOfVios.getClientPartitionId().equals(partitionHmcId)
                                && mappingOfVios.getClientPartitionSlot().equals(partitionSlotNo)) {
                            mappingOfVios.setCmpPartitionId(lpar.getId());
                            mappingOfVios.setClientWwpns(mappingFromDriver.getWwpns());
                            hmcVirtualFibreChannelMappingRepository.updateEntity(mappingOfVios);
                        }

                        mappingForDB.setCmpViosId(vios.getId());
                        mappingForDB.setServerViosName(vios.getName());
                    } else {
                        mappingForDB.setServerViosName("未知服务器");
                    }
                    // 再赋值vios那一端
                    if (mappingFromDriver.getServerAdapter() != null) {
                        ServerAdapter serverAdapter = mappingFromDriver.getServerAdapter();
                        mappingForDB.setServerViredOn(BooleanUtils.toBoolean(serverAdapter.getVariedOn()));
                        mappingForDB.setServerRequired(BooleanUtils.toBoolean(serverAdapter.getRequiredAdapter()));
                    }
                    if (mappingForDB.getId() == null) {
                        // id == null 说明是new出来的对象
                        hmcPartitionVfcAdapterRepository.save(mappingForDB);
                    } else {
                        hmcPartitionVfcAdapterRepository.updateEntity(mappingForDB);
                        oldFcMap.remove(partitionSlotNo);
                    }

                    HmcVirtualFibreChannelMapping mappingForView = new HmcVirtualFibreChannelMapping();
                    BeanUtils.copyProperties(mappingForDB, mappingForView);
                    lpar.getHmcVirtualFibreChannelMappings().add(mappingForView);
                }
            }
            // 删除在HMC上已经不存在的虚拟光纤通道mapping
            Iterator<HmcPartitionVfcAdapter> iteratorFc = oldFcMap.values().iterator();
            while (iteratorFc.hasNext()) {
                hmcPartitionVfcAdapterRepository.delete(iteratorFc.next());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void updateVirtualFibreChannelMappingForVios(HmcPartition vios, VirtualFibreChannelMappings mappings) {
        // 获取vios原始的光纤通道mapping
        List<HmcVirtualFibreChannelMapping> hmcMappings = hmcVirtualFibreChannelMappingRepository
                .listByViosId(vios.getId());
        Map<Integer, HmcVirtualFibreChannelMapping> oldFcMap = Maps.newHashMap();
        for (HmcVirtualFibreChannelMapping mapping : hmcMappings) {
            oldFcMap.put(mapping.getServerViosSlot(), mapping);
        }
        // 如果这个vios没有分配虚拟光纤通道，之前它的mapping信息全部删除
        if (null == mappings || null == mappings.getVirtualFibreChannelMappingList()) {
            Iterator<HmcVirtualFibreChannelMapping> iteratorFc = oldFcMap.values().iterator();
            while (iteratorFc.hasNext()) {
                hmcVirtualFibreChannelMappingRepository.delete(iteratorFc.next());
            }
        } else {
            // 更新或插入新的虚拟光纤通道mapping信息。
            List<VirtualFibreChannelMapping> listMapping = mappings.getVirtualFibreChannelMappingList();
            vios.setHmcVirtualFibreChannelMappings(new ArrayList<>());
            for (VirtualFibreChannelMapping mapping : listMapping) {
                ClientAdapter clientAdapter = mapping.getClientAdapter(); // 如果删除了映射的逻辑分区，clientAdapter是会为null的
                ServerAdapter serverAdapter = mapping.getServerAdapter(); // 暂时来看，serverAdapter是肯定不会为null的
                Port port = mapping.getPort(); // port是可能为空，如果没有把vfc映射到fc则port为空
                int viosSlotNo = Integer.parseInt(serverAdapter.getVirtualSlotNumber()); // 获取该映射在vios上的槽号
                int viosHmcId = Integer.parseInt(serverAdapter.getLocalPartitionId()); // 获取vios在hmc中的id
                int partitionSlotNo = Integer.parseInt(serverAdapter.getConnectingVirtualSlotNumber()); // 获取该映射在partition上的槽号
                int partitionHmcId = Integer.parseInt(serverAdapter.getConnectingPartitionID()); // 获取partition在hmc中的id
                HmcVirtualFibreChannelMapping mappingForDB = oldFcMap.get(viosSlotNo) == null
                        ? new HmcVirtualFibreChannelMapping()
                        : oldFcMap.get(viosSlotNo); // 创建要最终执行保存的对象
                HmcServer hmcServer = hmcServerRepository.getServerById(vios.getServerId());
                HmcPartition hmcPartition = hmcPartitionRepository.getByHmcPartitionId(partitionHmcId,
                        hmcServer.getId());
                // 如果该虚拟vfc通道对应的逻辑分区不存在或者已经被删除则不进行任何处理
                // if (hmcPartition == null || hmcPartition.getDeleted()) {
                // continue;
                // }
                // 执行入库
                mappingForDB.setCmpViosId(vios.getId());
                mappingForDB.setServerViosId(viosHmcId);
                mappingForDB.setServerViosName(vios.getName());
                mappingForDB.setServerViosSlot(viosSlotNo);
                mappingForDB.setServerRequired(BooleanUtils.toBoolean(serverAdapter.getRequiredAdapter()));
                mappingForDB.setServerViredOn(BooleanUtils.toBoolean(serverAdapter.getVariedOn()));
                mappingForDB.setCmpPartitionId(hmcPartition == null ? null : hmcPartition.getId());
                mappingForDB.setClientPartitionId(partitionHmcId);
                mappingForDB.setClientPartitionName(hmcPartition == null ? "分区不存在或已被删除(" + partitionHmcId + ")"
                        : hmcPartition.getName() + "(" + partitionHmcId + ")");
                mappingForDB.setClientPartitionSlot(partitionSlotNo);
                // 如果clientAdapter不为空，则赋值clientAdapter相关属性
                if (clientAdapter != null) {
                    mappingForDB.setClientRequired(BooleanUtils.toBoolean(clientAdapter.getRequiredAdapter()));
                    mappingForDB.setClientViredOn(BooleanUtils.toBoolean(clientAdapter.getVariedOn()));
                    mappingForDB.setClientWwpns(clientAdapter.getWwpns());
                } else {
                    mappingForDB.setClientRequired(null);
                    mappingForDB.setClientViredOn(null);
                    mappingForDB.setClientWwpns(null);
                }
                // 赋值物理fc卡
                if (port != null) {
                    HmcPhysicalFibreChannel hmcPhysicalFibreChannel = hmcPhysicalFibreChannelRepository
                            .getByUniqueDeviceId(port.getUniqueDeviceID());
                    if (hmcPhysicalFibreChannel != null) {
                        mappingForDB.setPhysicalUniqueDeviceId(hmcPhysicalFibreChannel.getUniqueDeviceId());
                        mappingForDB.setPhysicalUniqueDeviceId(hmcPhysicalFibreChannel.getUniqueDeviceId());
                        mappingForDB.setPhysicalFibreChannelId(hmcPhysicalFibreChannel.getId());
                    }
                }
                // 更新下partition的vfc中vios相关信息， 因为同步逻辑分区的时候尚未同步vios，会导致逻辑分区的vfc数据有缺失
                if (hmcPartition != null) {
                    HmcPartitionVfcAdapter mappingOfPartition = hmcPartitionVfcAdapterRepository
                            .queryMappingByPartitionIdAndSlot(hmcPartition.getId(), viosSlotNo);
                    if (mappingOfPartition != null && mappingOfPartition.getServerViosId().equals(viosHmcId)
                            && mappingOfPartition.getServerViosSlot().equals(viosSlotNo)) {
                        mappingOfPartition.setCmpViosId(vios.getId());
                        hmcPartitionVfcAdapterRepository.updateEntity(mappingOfPartition);
                    }
                }
                if (mappingForDB.getId() == null) {
                    // id == null 说明是new出来的对象
                    hmcVirtualFibreChannelMappingRepository.save(mappingForDB);
                } else {
                    hmcVirtualFibreChannelMappingRepository.updateEntity(mappingForDB);
                    oldFcMap.remove(viosSlotNo);
                }
                vios.getHmcVirtualFibreChannelMappings().add(mappingForDB);
            }
            // 删除在HMC上已经不存在的虚拟光纤通道mapping
            Iterator<HmcVirtualFibreChannelMapping> iteratorFc = oldFcMap.values().iterator();
            while (iteratorFc.hasNext()) {
                hmcVirtualFibreChannelMappingRepository.delete(iteratorFc.next());
            }
        }
    }

    /**
     * 更新virtual scsi adapter信息
     *
     * @param partition
     * @param vendorId
     */
    @Override
    public void updateNetworkAdapterForLpar(HmcPartition partition, Long vendorId) {
        CloudVendor cloudVendor = cloudVendorRepository.query(vendorId);
        if (cloudVendor == null) {
            throw new RuntimeException("未找到平台");
        }
        // 查询现有的虚拟以太网适配器
        List<HmcPartitionNetworkAdapter> oldNetworkAdapters = hmcPartitionNetworkAdapterRepository
                .getByPartitionId(partition.getId());
        Map<Integer, HmcPartitionNetworkAdapter> oldNetworkAdapterMap = new HashMap<>();
        for (HmcPartitionNetworkAdapter oldNetworkAdapter : oldNetworkAdapters) {
            oldNetworkAdapterMap.put(oldNetworkAdapter.getAdapterId(), oldNetworkAdapter);
        }
        // 从driver查询虚拟以太网适配器
        BocloudResult bocloudResult = hmcVirtualNetworkDriver.getClientNetworkAdapter(cloudVendor.getUuid(),
                partition.getUuid());
        if (bocloudResult.isFailed()) {
            throw new RuntimeException("获取虚拟以太网适配器失败：" + bocloudResult.getMessage());
        }
        ClientNetworkAdapterResponse adapterResponse = (ClientNetworkAdapterResponse) bocloudResult.getData();
        if (adapterResponse == null || adapterResponse.getEntries() == null
                || adapterResponse.getEntries().size() == 0) {
            logger.info("逻辑分区{}没有虚拟以太网适配器", partition.getName());
            for (HmcPartitionNetworkAdapter oldNetworkAdapter : oldNetworkAdapters) {
                hmcPartitionNetworkAdapterRepository.delete(oldNetworkAdapter);
            }
        } else {
            partition.setHmcPartitionNetworkAdapters(new ArrayList<>());
            for (ClientNetworkAdapterEntry adapterEntry : adapterResponse.getEntries()) {
                ClientNetworkAdapter adapterFromDriver = adapterEntry.getContent().getClientNetworkAdapter();

                int adapterId = Integer.parseInt(adapterFromDriver.getVirtualSlotNumber());
                int switchId = Integer.parseInt(adapterFromDriver.getVirtualSwitchID());
                HmcPartitionNetworkAdapter adapterToDB = oldNetworkAdapterMap.get(adapterId) == null
                        ? new HmcPartitionNetworkAdapter()
                        : oldNetworkAdapterMap.get(adapterId);
                HmcVirtualSwitch virtualSwitch = hmcVirtualSwitchRepository.getBySwitchId(switchId,
                        partition.getServerId());

                adapterToDB.setPartitionId(partition.getId());
                adapterToDB.setAdapterId(adapterId);
                adapterToDB.setVirtualSwitchId(switchId);
                adapterToDB.setVirtualSwitchName(virtualSwitch != null ? virtualSwitch.getName() : "未知");
                adapterToDB.setVirtualVlanId(Integer.parseInt(adapterFromDriver.getPortVlanId()));
                adapterToDB.setIsRequired(BooleanUtils.toBoolean(adapterFromDriver.getRequiredAdapter()));
                adapterToDB
                        .setIsTaggedVlanSupported(BooleanUtils.toBoolean(adapterFromDriver.getTaggedVlanSupported()));
                if (adapterToDB.getId() == null) {
                    hmcPartitionNetworkAdapterRepository.save(adapterToDB);
                } else {
                    hmcPartitionNetworkAdapterRepository.updateEntity(adapterToDB);
                }
                oldNetworkAdapterMap.remove(adapterId);
                partition.getHmcPartitionNetworkAdapters().add(adapterToDB);
            }
            for (HmcPartitionNetworkAdapter oldNetworkAdapter : oldNetworkAdapterMap.values()) {
                hmcPartitionNetworkAdapterRepository.delete(oldNetworkAdapter);
            }
        }
    }

    /**
     * 更新virtual scsi adapter信息
     *
     * @param partition
     * @param trunkAdapters @
     */
    @Override
    public void updateNetworkAdapterForVios(HmcPartition partition, TrunkAdapters trunkAdapters) {
        // 查询现有的虚拟以太网适配器
        List<HmcPartitionNetworkAdapter> oldNetworkAdapters = hmcPartitionNetworkAdapterRepository
                .getByPartitionId(partition.getId());
        Map<Integer, HmcPartitionNetworkAdapter> oldNetworkAdapterMap = new HashMap<>();
        for (HmcPartitionNetworkAdapter oldNetworkAdapter : oldNetworkAdapters) {
            oldNetworkAdapterMap.put(oldNetworkAdapter.getAdapterId(), oldNetworkAdapter);
        }
        if (trunkAdapters == null || trunkAdapters.getTrunkAdapters() == null
                || trunkAdapters.getTrunkAdapters().size() == 0) {
            logger.info("逻辑分区{}没有虚拟以太网适配器", partition.getName());
            for (HmcPartitionNetworkAdapter oldNetworkAdapter : oldNetworkAdapters) {
                hmcPartitionNetworkAdapterRepository.delete(oldNetworkAdapter);
            }
        } else {
            partition.setHmcPartitionNetworkAdapters(new ArrayList<>());
            for (TrunkAdapter adapterFromDriver : trunkAdapters.getTrunkAdapters()) {
                int adapterId = Integer.parseInt(adapterFromDriver.getVirtualSlotNumber());
                int switchId = Integer.parseInt(adapterFromDriver.getVirtualSwitchID());
                HmcPartitionNetworkAdapter adapterToDB = oldNetworkAdapterMap.get(adapterId) == null
                        ? new HmcPartitionNetworkAdapter()
                        : oldNetworkAdapterMap.get(adapterId);
                HmcVirtualSwitch virtualSwitch = hmcVirtualSwitchRepository.getBySwitchId(switchId,
                        partition.getServerId());

                adapterToDB.setPartitionId(partition.getId());
                adapterToDB.setAdapterId(adapterId);
                adapterToDB.setVirtualSwitchId(switchId);
                adapterToDB.setVirtualSwitchName(virtualSwitch != null ? virtualSwitch.getName() : "未知");
                adapterToDB.setVirtualVlanId(Integer.parseInt(adapterFromDriver.getPortVLANID()));
                adapterToDB.setIsRequired(BooleanUtils.toBoolean(adapterFromDriver.getRequiredAdapter()));
                adapterToDB
                        .setIsTaggedVlanSupported(BooleanUtils.toBoolean(adapterFromDriver.getTaggedVLANSupported()));
                adapterToDB.setTaggedVlanIds(adapterFromDriver.getTaggedVlanIds());
                adapterToDB.setPriority(Integer.parseInt(adapterFromDriver.getTrunkPriority()));
                if (adapterToDB.getId() == null) {
                    hmcPartitionNetworkAdapterRepository.save(adapterToDB);
                } else {
                    hmcPartitionNetworkAdapterRepository.updateEntity(adapterToDB);
                }
                oldNetworkAdapterMap.remove(adapterId);
                partition.getHmcPartitionNetworkAdapters().add(adapterToDB);
            }
            for (HmcPartitionNetworkAdapter oldNetworkAdapter : oldNetworkAdapterMap.values()) {
                hmcPartitionNetworkAdapterRepository.delete(oldNetworkAdapter);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void updateVirtualScsiAdapterForLpar(HmcPartition partition, Long vendorId) {
        // 云平台
        CloudVendor vendor = cloudVendorRepository.query(vendorId);
        if (null == vendor) {
            throw new RuntimeException("未找到平台");
        }
        // 查询该逻辑分区下面的所有虚拟scsi适配器
        List<HmcPartitionScsiAdapter> oldScsiAdapters = hmcPartitionScsiAdapterRepository
                .queryByPartitionId(partition.getId());
        Map<Integer, HmcPartitionScsiAdapter> oldScsiAdapterMap = new HashMap<>();
        for (HmcPartitionScsiAdapter oldScsiAdapter : oldScsiAdapters) {
            oldScsiAdapterMap.put(oldScsiAdapter.getAdapterId(), oldScsiAdapter);
        }
        // 通过接口查询逻辑分区相信信息
        BocloudResult result = partitionDriver.getPartitionAttribute(vendor.getUuid(), partition.getUuid(), false);
        if (result.isFailed()) {
            throw new RuntimeException("获取虚拟scsi失败：" + result.getMessage());
        }
        LogicalPartitionEntry entry = (LogicalPartitionEntry) result.getData();
        // 执行更新或保存
        List<HmcPartitionScsiAdapter> hmcPartitionScsiAdapters = new ArrayList<>();
        if (null == entry.getContent().getLogicalPartition().getVirtualSCSIClientAdapters()) {
            logger.info("逻辑分区{}没有虚拟scsi适配器", partition.getName());
            for (HmcPartitionScsiAdapter oldScsiAdapter : oldScsiAdapters) {
                hmcPartitionScsiAdapterRepository.delete(oldScsiAdapter);
            }
        } else {
            for (Link link : entry.getContent().getLogicalPartition().getVirtualSCSIClientAdapters().getLink()) {
                BocloudResult scsiResult = partitionDriver.getVirtualScsiAdapters(vendor.getUuid(), link.getHref());
                if (scsiResult.isFailed()) {
                    logger.error("get lpar scsi adapter failure! result={}", scsiResult);
                    continue;
                }
                VirtualSCSIClientAdapterEntry scsiEntry = (VirtualSCSIClientAdapterEntry) scsiResult.getData();
                if (null == scsiEntry.getContent().getVirtualScsiClientAdapter()) {
                    logger.warn("get lpar scsi adapter failure! result={}", scsiEntry);
                    continue;
                }
                VirtualSCSIClientAdapter hmcScsiAdapter = scsiEntry.getContent().getVirtualScsiClientAdapter();
                int adapterId = Integer.parseInt(hmcScsiAdapter.getVirtualSlotNumber());
                HmcPartitionScsiAdapter lParScsiAdapter = oldScsiAdapterMap.get(adapterId);

                if (lParScsiAdapter == null) {
                    lParScsiAdapter = new HmcPartitionScsiAdapter();
                    lParScsiAdapter.setAdapterId(adapterId);
                    lParScsiAdapter.setIsRequired(Boolean.parseBoolean(hmcScsiAdapter.getRequiredAdapter()));
                    lParScsiAdapter.setIsRequired(Boolean.parseBoolean(hmcScsiAdapter.getRequiredAdapter()));
                    lParScsiAdapter.setLocationCode(hmcScsiAdapter.getLocationCode());
                    lParScsiAdapter.setPartitionId(partition.getId());
                    // remote lpar info
                    HmcPartition remoteLpar = hmcPartitionRepository.get(
                            Integer.parseInt(hmcScsiAdapter.getRemoteLogicalPartitionID()), partition.getServerId());
                    lParScsiAdapter.setRemotePartitionId(remoteLpar == null ? null : remoteLpar.getId());
                    lParScsiAdapter.setRemotePartitionName(remoteLpar == null ? null : remoteLpar.getName());
                    lParScsiAdapter
                            .setRemotePartitionHmcId(Integer.parseInt(hmcScsiAdapter.getRemoteLogicalPartitionID()));
                    lParScsiAdapter.setRemoteSlotNumber(Integer.parseInt(hmcScsiAdapter.getRemoteSlotNumber()));
                    lParScsiAdapter.setType(hmcScsiAdapter.getAdapterType());
                    hmcPartitionScsiAdapterRepository.save(lParScsiAdapter);
                } else {
                    lParScsiAdapter.setAdapterId(adapterId);
                    lParScsiAdapter.setIsRequired(Boolean.parseBoolean(hmcScsiAdapter.getRequiredAdapter()));
                    lParScsiAdapter.setLocationCode(hmcScsiAdapter.getLocationCode());
                    lParScsiAdapter.setPartitionId(partition.getId());
                    // remote lpar info
                    HmcPartition remoteLpar = hmcPartitionRepository.get(
                            Integer.parseInt(hmcScsiAdapter.getRemoteLogicalPartitionID()), partition.getServerId());
                    lParScsiAdapter.setRemotePartitionId(remoteLpar == null ? null : remoteLpar.getId());
                    lParScsiAdapter.setRemotePartitionName(remoteLpar == null ? null : remoteLpar.getName());
                    lParScsiAdapter
                            .setRemotePartitionHmcId(Integer.parseInt(hmcScsiAdapter.getRemoteLogicalPartitionID()));
                    lParScsiAdapter.setRemoteSlotNumber(Integer.parseInt(hmcScsiAdapter.getRemoteSlotNumber()));
                    lParScsiAdapter.setType(hmcScsiAdapter.getAdapterType());
                    hmcPartitionScsiAdapterRepository.updateEntity(lParScsiAdapter);
                    oldScsiAdapterMap.remove(adapterId);
                }
                hmcPartitionScsiAdapters.add(lParScsiAdapter);
                partition.setHmcPartitionScsiAdapters(hmcPartitionScsiAdapters);
            }
            // 删除已经不存在的虚拟适配器
            for (HmcPartitionScsiAdapter oldScsiAdapter : oldScsiAdapterMap.values()) {
                hmcPartitionScsiAdapterRepository.delete(oldScsiAdapter);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void updateVirtualScsiAdapterForVios(HmcPartition partition, VirtualSCSIMappings virtualSCSIMappings) {
        // 查询该逻辑分区下面的所有虚拟scsi适配器
        List<HmcPartitionScsiAdapter> oldScsiAdapters = hmcPartitionScsiAdapterRepository
                .queryByPartitionId(partition.getId());
        Map<Integer, HmcPartitionScsiAdapter> oldScsiAdapterMap = new HashMap<>();
        for (HmcPartitionScsiAdapter oldScsiAdapter : oldScsiAdapters) {
            oldScsiAdapterMap.put(oldScsiAdapter.getAdapterId(), oldScsiAdapter);
        }
        // 开始处理
        if (virtualSCSIMappings == null || virtualSCSIMappings.getVirtualScsiMapping() == null
                || virtualSCSIMappings.getVirtualScsiMapping().size() == 0) {
            logger.info("逻辑分区{}没有虚拟scsi适配器", partition.getName());
            for (HmcPartitionScsiAdapter oldScsiAdapter : oldScsiAdapters) {
                hmcPartitionScsiAdapterRepository.delete(oldScsiAdapter);
            }
        } else {
            // 由于一条SCSI通道可以对于多个虚拟盘，接口会返回多条相同的SCSI数据，所以要去重
            Map<Integer, VirtualSCSIMapping> virtualSCSIMappingMap = new HashMap<>();
            for (VirtualSCSIMapping virtualSCSIMapping : virtualSCSIMappings.getVirtualScsiMapping()) {
                virtualSCSIMappingMap.put(
                        Integer.parseInt(virtualSCSIMapping.getServerAdapter().getVirtualSlotNumber()),
                        virtualSCSIMapping);
            }
            // 开始新增和更新
            partition.setHmcPartitionScsiAdapters(new ArrayList<>());
            for (Integer adapterId : virtualSCSIMappingMap.keySet()) {
                VirtualSCSIMapping virtualSCSIMapping = virtualSCSIMappingMap.get(adapterId);
                int remoteLogicalPartitionId = Integer
                        .parseInt(virtualSCSIMapping.getServerAdapter().getRemoteLogicalPartitionId());
                HmcPartition remoteLpar = hmcPartitionRepository.getByHmcPartitionId(remoteLogicalPartitionId,
                        partition.getServerId());
                // 如果该虚拟scsi对应的逻辑分区不存在或者已经被删除则直接不进行任何处理
                // if (remoteLpar == null || remoteLpar.getDeleted()) {
                // continue;
                // }
                // 执行数据入库
                HmcPartitionScsiAdapter scsiAdapter = oldScsiAdapterMap.get(adapterId) == null
                        ? new HmcPartitionScsiAdapter()
                        : oldScsiAdapterMap.get(adapterId);
                scsiAdapter.setPartitionId(partition.getId());
                scsiAdapter.setAdapterId(adapterId);
                scsiAdapter.setRemotePartitionId(remoteLpar == null ? null : remoteLpar.getId());
                scsiAdapter.setRemotePartitionHmcId(remoteLogicalPartitionId);
                scsiAdapter.setRemotePartitionName(remoteLpar == null ? "分区不存在或已被删除" : remoteLpar.getName());
                scsiAdapter.setRemoteSlotNumber(
                        Integer.parseInt(virtualSCSIMapping.getServerAdapter().getRemoteSlotNumber()));
                scsiAdapter.setType(virtualSCSIMapping.getServerAdapter().getAdapterType());
                scsiAdapter.setIsRequired(
                        BooleanUtils.toBoolean(virtualSCSIMapping.getServerAdapter().getRequiredAdapter()));
                scsiAdapter.setLocationCode(virtualSCSIMapping.getServerAdapter().getLocationCode());
                if (scsiAdapter.getId() == null) {
                    hmcPartitionScsiAdapterRepository.save(scsiAdapter);
                } else {
                    hmcPartitionScsiAdapterRepository.updateEntity(scsiAdapter);
                }
                oldScsiAdapterMap.remove(adapterId);
                partition.getHmcPartitionScsiAdapters().add(scsiAdapter);
            }
            // 删除已经不存在的scsi
            for (HmcPartitionScsiAdapter oldScsiAdapter : oldScsiAdapterMap.values()) {
                hmcPartitionScsiAdapterRepository.delete(oldScsiAdapter);
            }
        }
    }

    @Override
    public BocloudResult create(HmcPartition par, RequestContext context) {
        Long serverId = par.getServerId();
        if (null == serverId) {
            return new BocloudResult(false, "缺少服务Id");
        }
        HmcServer server = null;
        try {
            server = hmcServerRepository.getServerById(serverId);
            if (null == server) {
                logger.error("get HMC server failure!");
                return new BocloudResult(false, "服务器不存在!");
            }
        } catch (Exception e) {
            return new BocloudResult(false, "创建失败");
        }

        // 云平台ID
        Long vendorId = server.getVendorId();
        // 云供应商
        CloudVendor vendor = null;
        try {
            vendor = cloudVendorRepository.query(vendorId);
            if (null == vendor) {
                logger.error("get cloudVendor failure!");
                return new BocloudResult(false, "云平台不存在!");
            }
        } catch (Exception e) {
            return new BocloudResult(false, "创建失败");
        }

        BocloudResult<HmcPartition> serverResult = hmcServerBuilder.prepare(par, vendor, context);
        if (serverResult.isFailed()) {
            return new BocloudResult(false, serverResult.getMessage());
        }
        HmcPartition lpar = serverResult.getData();
        lpar.setServerUuid(server.getUuid());
        // 启动一个线程从MQ上获取数据
        taskExecutor.submit(() -> {
            hmcServerBuilder.builder(vendorId, lpar, context);
        });
        return new BocloudResult(true, "创建任务已经下发，正在执行……");
    }

    @Override
    public BocloudResult modify(HmcPartition partition, RequestContext context) {
        Long partitionId = partition.getId();
        String path = HmcPartition.class.getSimpleName() + "_" + partitionId;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                logger.warn("Get BocloudLock time out!");
                return new BocloudResult(false, "请求超时");
            }
            HmcPartition oldPartition = hmcPartitionRepository.getById(partitionId);
            if (null == oldPartition) {
                logger.error("lpar {} does not exist!", partitionId);
                return new BocloudResult(false, "ID为[" + partitionId + "]的分区不存在");
            }
            HmcServer server = hmcServerRepository.getServerById(oldPartition.getServerId());
            if (null == server) {
                logger.error("hmc server {} does not exist!", oldPartition.getServerId());
                return new BocloudResult(false, "ID为[" + oldPartition.getServerId() + "]的HMC服务器不存在");
            }
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            if (null == vendor) {
                logger.error("vendor {} does not exist!", server.getVendorId());
                return new BocloudResult(false, "ID为[" + server.getVendorId() + "]的云平台不存在");
            }
            // 启动一个线程从MQ上获取数据
            taskExecutor.submit(() -> {

                String operate = vendor.getType().toLowerCase() + ".partition";
                String content = "HMC分区[" + oldPartition.getName() + "]修改失败";
                try {
                    ResourceEvent event = null;
                    String vendorUuid = vendor.getUuid();

                    // 更新分区状态
                    String oldStatus = oldPartition.getStatus();
                    oldPartition.setStatus("PARTITION_UPDATING");
                    hmcPartitionRepository.update(oldPartition);

                    Boolean isVios = false;
                    if ("Virtual IO Server".equals(oldPartition.getPartitionType())) {
                        isVios = true;
                    }

                    // 如果开启了同步，先设置挂起同步
                    if ("On".equals(partition.getCurrentProfileSync())) {
                        if (isVios) {
                            HmcPartition updateVios = new HmcPartition();
                            updateVios.setCurrentProfileSync("Suspended");

                            BocloudResult updateResult = partitionDriver.updateVirtualIOServer(vendorUuid, JSONObject
                                            .parseObject(JSONObject.toJSONString(updateVios), HmcPartitionModel.class),
                                    server.getUuid(), oldPartition.getUuid());
                            if (updateResult.isFailed()) {
                                logger.error("Failed to update vios {} profileSync configuration {}",
                                        partition.getName(), updateResult);
                                event = new ResourceEvent(partition.getId(), ServerAction.UPDATE.name(), "失败",
                                        context.getTarget(), new Date(), "HMC", vendor.getId(), context.getCatalog());
                                content = "HMC vios[" + partition.getName() + "]编辑失败，设置同步分区为挂起失败";
                                resourceEventRepository.save(event);
                                resourceEventPublisher.send(new OperateResult(updateResult.isSuccess(), content,
                                        operate, MapTools.simpleMap("vendorId", vendor.getId()), operateCategory,
                                        context));
                                return;
                            }
                        } else {
                            HmcPartition updateLpar = new HmcPartition();
                            updateLpar.setCurrentProfileSync("Suspended");

                            BocloudResult updateResult = partitionDriver.updateLogicalPartition(vendorUuid, JSONObject
                                            .parseObject(JSONObject.toJSONString(updateLpar), HmcPartitionModel.class),
                                    server.getUuid(), oldPartition.getUuid());

                            if (updateResult.isFailed()) {
                                logger.error("Failed to update partition {} profileSync configuration {}",
                                        partition.getName(), updateResult);
                                event = new ResourceEvent(partition.getId(), ServerAction.UPDATE.name(), "失败",
                                        context.getTarget(), new Date(), "HMC", vendor.getId(), context.getCatalog());
                                content = "HMC逻辑分区[" + partition.getName() + "]编辑失败，设置同步分区为挂起失败";
                                resourceEventRepository.save(event);
                                resourceEventPublisher.send(new OperateResult(updateResult.isSuccess(), content,
                                        operate, MapTools.simpleMap("vendorId", vendor.getId()), operateCategory,
                                        context));
                                return;
                            }
                        }
                        // 设置挂起同步成功，同步数据库信息
                        oldPartition.setCurrentProfileSync("Suspended");
                        hmcPartitionRepository.update(oldPartition);
                    }

                    BocloudResult result = null;
                    if (isVios) {
                        result = partitionDriver.updateVirtualIOServer(vendorUuid,
                                JSONObject.parseObject(JSONObject.toJSONString(partition), HmcPartitionModel.class),
                                server.getUuid(), oldPartition.getUuid());
                    } else {
                        result = partitionDriver.updateLogicalPartition(vendorUuid,
                                JSONObject.parseObject(JSONObject.toJSONString(partition), HmcPartitionModel.class),
                                server.getUuid(), oldPartition.getUuid());
                    }
                    if (result.isSuccess()) {
                        if (isVios) {
                            VirtualIOServerEntry entry = (VirtualIOServerEntry) result.getData();
                            hmcDatabaseHelper.updatePartition(oldPartition, entry.getContent().getVirtualIOServer(),
                                    null, false, context.getTarget());
                        } else {
                            LogicalPartitionEntry entry = (LogicalPartitionEntry) result.getData();
                            hmcDatabaseHelper.updatePartition(oldPartition, entry.getContent().getLogicalPartition(),
                                    null, false, context.getTarget());
                        }
                        event = new ResourceEvent(partition.getId(), ServerAction.UPDATE.name(), "成功",
                                context.getTarget(), new Date(), "HMC", vendor.getId(), context.getCatalog());
                        content = "HMC分区[" + oldPartition.getName() + "]编辑成功";
                    } else {
                        // 恢复原来的状态
                        oldPartition.setStatus(oldStatus);
                        hmcPartitionRepository.update(oldPartition);
                        event = new ResourceEvent(partition.getId(), ServerAction.UPDATE.name(), "失败",
                                context.getTarget(), new Date(), "HMC", vendor.getId(), context.getCatalog());
                        content = "HMC分区[" + oldPartition.getName() + "]编辑失败";
                    }
                    resourceEventRepository.save(event);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("修改HMC分区失败", e);
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult(true, "编辑任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("Modify cloudServer fail:", e);
            return new BocloudResult(false, "编辑失败");
        }
    }

    @Override
    public BocloudResult remove(Long id, List<Long> vds, List<Long> vfcs, RequestContext context) {
        String path = HmcPartition.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                logger.warn("Get BocloudLock time out!");
                return new BocloudResult(false, "请求超时");
            }
            HmcPartition partition = hmcPartitionRepository.getById(id);
            if (null == partition) {
                logger.warn("Partition data not exist, {}", id);
                return new BocloudResult(false, "数据不存在");
            }
            HmcServer server = hmcServerRepository.getServerById(partition.getServerId());
            if (null == server) {
                logger.warn("HMC server data not exist, {}", partition.getServerId());
                return new BocloudResult(false, "服务器不存在");
            }
            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            if (null == vendor) {
                logger.error("get cloudVendor failure, {}", server.getVendorId());
                return new BocloudResult(false, "删除失败!");
            }
            taskExecutor.submit(() -> {
                String operate = vendor.getType().toLowerCase() + ".partition";
                String content = "HMC分区[" + partition.getName() + "]删除失败";
                try {
                    ResourceEvent event = null;

                    if (HmcStatus.PARTITION.INSTALLING.getName().equals(partition.getStatus())) {
                        // 先将装机任务取消
                        logger.warn("分区{}取消AIX安装", partition.getName());
                        nimService.cancel(partition.getId(), context);
                    }

                    // 更新分区状态
                    String oldStatus = partition.getStatus();
                    partition.setStatus("PARTITION_DELETING");
                    hmcPartitionRepository.update(partition);

                    BocloudResult result;
                    Boolean isVios = false;
                    if ("Virtual IO Server".equals(partition.getPartitionType())) {
                        isVios = true;
                    }
                    result = partitionDriver.delete(vendor.getUuid(), server.getUuid(), partition.getUuid(), isVios);
                    boolean success = false;
                    // 排除删除hmc时, hmc数据实际已经不存在的情況
                    if (result.isSuccess() || result.toString().contains(NOT_EXIST)) {
                        success = true;
                        event = new ResourceEvent(id, ServerAction.DELETE.name(), "成功", context.getTarget(), new Date(),
                                "HMC", vendor.getId(), context.getCatalog());
                        content = "HMC分区[" + partition.getName() + "]删除成功";
                    } else {
                        // 恢复原来的状态
                        partition.setStatus(oldStatus);
                        hmcPartitionRepository.update(partition);
                        event = new ResourceEvent(id, ServerAction.DELETE.name(), "失败", context.getTarget(), new Date(),
                                "HMC", vendor.getId(), context.getCatalog());
                        content = "HMC分区[" + partition.getName() + "]删除失败,失败原因:[" + result.getMessage() + "]";
                        resourceEventRepository.save(event);
                        resourceEventPublisher.send(new OperateResult(success, content, operate,
                                MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                        return;
                    }

                    if (!isVios) {
                        // 删除逻辑分区,删除/取消分配关联盘
//						Map<String, Object> params = MapTools.simpleMap("serverId", server.getId());
//						params.put("vendorId", vendor.getId());
//						params.put("lparId", id);
                        HmcStorageFcVdListParams listParams = new HmcStorageFcVdListParams();
                        listParams.setServerId(server.getId());
                        listParams.setVendorId(vendor.getId());
                        listParams.setLparId(id);
                        result = hmcVolumeGroupService.listVd(server.getId(), vendor.getId(), id);
                        if (result.isSuccess()) {
                            List<HmcVirtualDisk> sqlVds = JSONObject
                                    .parseArray(JSONObject.toJSONString(result.getData()), HmcVirtualDisk.class);
                            for (HmcVirtualDisk vd : sqlVds) {
                                HmcVolumeGroup vg = hmcVolumeGroupRepository.query(vd.getVgId());
                                if (vds.contains(vd.getId())) {
                                    // 这里说明前端选择了关联虚拟盘, 调用删除虚拟磁盘
//									Map<String, Object> deleteParams = MapTools.simpleMap("serverId", server.getId());
//									deleteParams.put("vendorId", vendor.getId());
//									deleteParams.put("viosId", vg.getViosId());
//									deleteParams.put("groupName", vg.getGroupName());
//									deleteParams.put("diskName", vd.getDiskName());
//									deleteParams.put("diskCapacity", vd.getDiskCapacity());
                                    HmcVolumeGroupParams createVdParams = new HmcVolumeGroupParams();
                                    createVdParams.setServerId(server.getId());
                                    createVdParams.setVendorId(vendor.getId());
                                    createVdParams.setViosId(vg.getViosId());
                                    createVdParams.setGroupName(vg.getGroupName());
                                    createVdParams.setDiskName(vd.getDiskName());
                                    createVdParams.setDiskCapacity(vd.getDiskCapacity());
                                    result = hmcVolumeGroupService.deleteVd(createVdParams,
                                            context);
                                    if (result.isFailed()) {
                                        logger.warn("删除逻辑分区{}关联虚拟磁盘{}失败", partition.getName(), vd.getDiskName());
                                        success = false;
                                    }
                                } else {
                                    // 这里说明前端没有选择删除该虚拟盘, 做取消分配即可
//									Map<String, Object> unAssignParams = MapTools.simpleMap("serverId", server.getId());
//									unAssignParams.put("vendorId", vendor.getId());
//									unAssignParams.put("viosId", vg.getViosId());
//									unAssignParams.put("diskId", vd.getId());
                                    HmcStorageUnassign unassign = new HmcStorageUnassign();
                                    unassign.setServerId(server.getId());
                                    unassign.setVendorId(vendor.getId());
                                    unassign.setViosId(vg.getViosId());
                                    unassign.setDiskId(vd.getId());
                                    result = hmcVolumeGroupService.unAssignVd(unassign,
                                            context);
                                    if (result.isFailed()) {
                                        logger.warn("取消分配逻辑分区{}关联虚拟磁盘{}失败", partition.getName(), vd.getDiskName());
                                        success = false;
                                    }
                                }
                                // 防止vios的IO太频繁, 等1m
                                TimeUnit.MINUTES.sleep(1);
                            }
                        }
                    }
                    // 刪除中的分区及其相关的数据
                    hmcDatabaseHelper.removePartition(partition.getId(), context.getTarget());
                    // 删除CloudServer中对应的虚拟机
                    cloudServerRepository.removeByUuid(partition.getUuid(), context.getTarget());

                    resourceEventRepository.save(event);
                    resourceEventPublisher.send(new OperateResult(success, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("删除HMC分区失败", e);
                    resourceEventPublisher.send(new OperateResult(false, content, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult(true, "删除任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("remove HMC partition failure:", e);
            return new BocloudResult(false, "删除失败");
        }
    }

    /**
     * HMC分区激活
     *
     * @param profileId HMC分区概要文件ID
     * @return 操作结果
     * @author sxp
     * @since Jun 12, 2018
     */
    @Override
    public BocloudResult powerOn(Long profileId, RequestContext context) {
        try {
            HmcProfile profile = hmcProfileRepository.queryById(profileId);
            if (null == profile) {
                return new BocloudResult(false, "唯一标识为[" + profileId + "]的HMC概要文件不存在");
            }
            HmcPartition partition = hmcPartitionRepository.getById(profile.getPartitionId());
            if (partition == null) {
                return new BocloudResult(false, "唯一标识为[" + profile.getPartitionId() + "]的HMC分区不存在");
            }
            HmcServer hmcServer = hmcServerRepository.getServerById(partition.getServerId());
            if (null == hmcServer) {
                logger.error("hmcServer {} does not exist!", partition.getServerId());
                return new BocloudResult(false, "ID为[" + partition.getServerId() + "]的小机不存在");
            }
            String status = partition.getStatus();
            if (!HmcPartitionStatus.Not_Activated.getStatus().equals(status)) {
                return new BocloudResult(false, "当前分区不是[未激活]状态，不能执行激活操作");
            }

            String lparUuid = partition.getUuid();
            if (StringUtils.isEmpty(lparUuid)) {
                return new BocloudResult(false, "当前分区对应的uuid为空");
            }

            String partitionType = partition.getPartitionType();

            Long serverId = partition.getServerId();
            if (serverId == null) {
                return new BocloudResult(false, "当前分区所属的服务器唯一标识为空");
            }

            HmcServer server = hmcServerRepository.getServerById(serverId);
            if (server == null) {
                return new BocloudResult(false, "唯一标识为[" + serverId + "]的HMC服务器不存在");
            }

            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            if (vendor == null) {
                return new BocloudResult(false, "唯一标识为[" + server.getVendorId() + "]的云平台不存在");
            }
            String vendorUuid = vendor.getUuid();

            Boolean isVios = false;
            if (HmcPartitionType.VIOS.getType().equals(partitionType)) {
                isVios = true;
            }

            BocloudResult result = partitionDriver.powerOnPartition(vendorUuid, partition.getUuid(), profile.getUuid(),
                    isVios);
            if (result.isFailed()) {
                return new BocloudResult(false, "分区激活失败:" + result.getMessage());
            }
            JSONObject jobJson = (JSONObject) result.getData();
            String jobId = jobJson.getString(Constant.HMC_JOB_ID);
            if (StringUtils.isEmpty(jobId)) {
                return new BocloudResult(false, "HMC分区激活失败：生成的任务ID是空");
            }

            partition.setHmcLparProfile(profile);
            String description = "分区[" + partition.getName() + "]激活";
            partition.setStatus(HmcStatus.PARTITION.POWERON_RUNNING.toString());
            asynGetJobStatus(partition, vendorUuid, jobId, description, context, hmcServer.getVendorId());

            return result;
        } catch (Exception e) {
            logger.error("HMC server powerOn fail:", e);
            return new BocloudResult(false, "分区激活失败:" + e.getMessage());
        }
    }

    /**
     * 异步查询任务执行状态
     *
     * @param lpar        lpar分区
     * @param vendorUuid  平台uuid
     * @param jobId       任务id
     * @param description 任务描述
     * @param vendorId    平台id
     * @author sxp
     * @since Jun 13, 2018
     */
    private void asynGetJobStatus(HmcPartition lpar, String vendorUuid, String jobId, String description,
                                  RequestContext context, Long vendorId) {
        taskExecutor.submit(() -> {
            logger.info("{}的jobId为{}", description, jobId);
            Object data = MapTools.simpleMap("serverId", lpar.getServerId());
            OperateResult operateResult = new OperateResult(true, "success", OPERATE_RESULT_TYPE, data,
                    OperateCategory.ResourceEvent, context);

            try {
                // 更新分区状态
                hmcPartitionRepository.update(lpar);

                BocloudResult statusResult = commonDriver.getJobStatus(vendorUuid, jobId);
                if (statusResult.isSuccess()) {
                    operateResult.setSuccess(true);
                    operateResult.setMessage(description + "任务执行成功");
                    if (HmcStatus.PARTITION.POWERON_RUNNING.getName().equals(lpar.getStatus())) {
                        // 设置这个概要文件为这个分区最后激活的
                        hmcDatabaseHelper.updateLastActivatedProfile(lpar.getId(), lpar.getHmcLparProfile().getId());
                        // 设置这个概要文件 为Active
                        hmcDatabaseHelper.setActivedProfile(lpar.getId(), lpar.getHmcLparProfile().getId());
                        if (!HmcPartitionType.VIOS.getType().equals(lpar.getPartitionType())) {
                            // 如果当前虚拟机是正在启动，则表示尚未激活成功，还需要再等一等
                            long start = System.currentTimeMillis();
                            while (System.currentTimeMillis() - start < 30 * 1000) {
                                BocloudResult result = partitionDriver.getPartitionAttribute(vendorUuid, lpar.getUuid(),
                                        false);
                                if (result.isFailed()) {
                                    throw new RuntimeException(
                                            "获取逻辑分区[" + lpar.getName() + "]信息失败：" + result.getMessage());
                                }
                                String status = ((LogicalPartitionEntry) result.getData()).getContent()
                                        .getLogicalPartition().getPartitionState();
                                if (!HmcPartitionStatus.Starting.getStatus().equals(status)) {
                                    break;
                                }
                                logger.info("lpar[" + lpar.getName() + "] is starting, it will wait 1 second");
                                Thread.sleep(1000);
                                continue;
                            }
                            // 更新虚拟scsi适配器信息
                            updateVirtualScsiAdapterForLpar(lpar, vendorId);
                            // 更新虚拟vfc适配器信息
                            updateVirtualFibreChannelMappingForLpar(lpar, vendorId);
                            // 更新虚拟以太网适配器信息
                            updateNetworkAdapterForLpar(lpar, vendorId);
                        } else {
                            VirtualIOServerEntry entry = null;
                            // 如果当前虚拟机是正在启动，则表示尚未激活成功，还需要再等一等
                            long start = System.currentTimeMillis();
                            while (System.currentTimeMillis() - start < 30 * 1000) {
                                BocloudResult result = partitionDriver.getPartitionAttribute(vendorUuid, lpar.getUuid(),
                                        true);
                                if (result.isFailed()) {
                                    throw new RuntimeException(
                                            "获取vios[" + lpar.getName() + "]虚拟scsi失败：" + result.getMessage());
                                }
                                entry = (VirtualIOServerEntry) result.getData();
                                String status = entry.getContent().getVirtualIOServer().getPartitionState();
                                if (!HmcPartitionStatus.Starting.getStatus().equals(status)) {
                                    break;
                                }
                                logger.info("vios[" + lpar.getName() + "] is starting, it will wait 1 second");
                                Thread.sleep(1000);
                                continue;
                            }
                            // 更新虚拟scsi适配器信息
                            updateVirtualScsiAdapterForVios(lpar,
                                    entry.getContent().getVirtualIOServer().getVirtualSCSIMappings());
                            // 更新虚拟vfc适配器信息
                            updateVirtualFibreChannelMappingForVios(lpar,
                                    entry.getContent().getVirtualIOServer().getVirtualFibreChannelMappings());
                            // 更新虚拟以太网适配器信息
                            updateNetworkAdapterForVios(lpar,
                                    entry.getContent().getVirtualIOServer().getTrunkAdapters());
                        }
                    } else {
                        if (HmcPartitionType.AIX_LINUX.getType().equals(lpar.getPartitionType())) {
                            // 关机/重启成功逻辑分区，装机任务取消，设置为取消装机结果
                            if (HmcStatus.PARTITION.INSTALLING.getName().equals(lpar.getStatus())) {
                                // 关机/重启成功逻辑分区，装机任务取消
                                logger.warn("分区{}取消AIX安装", lpar.getName());
                                nimService.cancel(lpar.getId(), context);
                            }
                        }

                        if (HmcStatus.PARTITION.POWEROFF_RUNNING.getName().equals(lpar.getStatus())) {
                            // 设置这个概要文件 为Unactived
                            hmcDatabaseHelper.setUnactivedProfile(lpar.getId());
                        }
                    }
                } else {
                    operateResult.setSuccess(false);
                    operateResult.setMessage(description + "：" + statusResult.getMessage());
                }
                // 不管任务成功失败，分区的属性值都可能更新。
                syncPartition(lpar, vendorUuid, description, operateResult, false, context.getTarget());
            } catch (Exception e) {
                logger.error(description + "任务执行状态出现异常", e);
                operateResult.setSuccess(false);
                operateResult.setMessage(description + "任务执行状态出现异常：" + e.getMessage());
            }

            resourceEventPublisher.send(operateResult);
        });
    }

    /**
     * 更新分区的状态
     *
     * @author sxp
     * @since Jun 14, 2018
     */
    @Override
    public void updateStatus(HmcPartition partition, String vendorUuid, String description,
                             OperateResult operateResult) {
        // 调用接口查询分区的当前状态
        String uuid = partition.getUuid();
        Boolean isVios = partition.isVios();
        BocloudResult tmpResult = partitionDriver.queryPartitionState(vendorUuid, uuid, isVios);

        if (tmpResult.isFailed()) {
            if (null != operateResult) {
                operateResult.setSuccess(false);
                operateResult.setMessage(description + "任务执行成功，但是获取分区的状态出错：" + tmpResult.getMessage());
            }
        } else {
            partition.setStatus((String) tmpResult.getData());
            hmcPartitionRepository.update(partition);
        }
    }

    private static final String COMMAND = "lssyscfg -r lpar -m %s -F lpar_id,state,rmc_state,rmc_ipaddr,os_version,dlpar_mem_capable,dlpar_proc_capable,dlpar_io_capable";

    @Override
    public void syncPartition(HmcPartition partition, String vendorUuid, String description,
                              OperateResult operateResult, Boolean syncAllInfo, long userId) {
        String uuid = partition.getUuid();
        Boolean isVios = partition.isVios();
        BocloudResult result = partitionDriver.getPartitionAttribute(vendorUuid, uuid, isVios);

        if (result.isFailed()) {
            if (null != operateResult) {
                operateResult.setSuccess(false);
                operateResult.setMessage(description + "任务执行成功，但是获取分区的属性失败：" + result.getMessage());
            }
        } else {
            if (isVios) {
                VirtualIOServerEntry entry = (VirtualIOServerEntry) result.getData();
                hmcDatabaseHelper.updatePartition(partition, entry.getContent().getVirtualIOServer(), null, syncAllInfo,
                        userId);
                // 如果当前逻辑分区的状态是正在启动，则要另外启动一个线程等待状态变化
                if (entry.getContent().getVirtualIOServer().getPartitionState()
                        .equals(HmcPartitionStatus.Starting.getStatus())) {
                    logger.info("VIOS：" + partition.getName() + "的状态是"
                            + entry.getContent().getVirtualIOServer().getPartitionState() + "，将会建立线程定期刷新该VIOS状态");
                    final long partitionId = partition.getId();
                    taskExecutor.submit(() -> {
                        int failedCnt = 0;
                        while (true) {
                            try {
                                BocloudResult result1 = partitionDriver.getPartitionAttribute(vendorUuid, uuid, isVios);
                                if (result1.isFailed()) {
                                    logger.warn("获取VIOS信息失败：" + result1.getMessage());
                                    failedCnt++;
                                    // 失败次数达到3次则放弃，否则继续尝试
                                    if (failedCnt >= 3) {
                                        break;
                                    } else {
                                        Thread.sleep(1000);
                                        continue;
                                    }
                                }
                                VirtualIOServerEntry entry1 = (VirtualIOServerEntry) result1.getData();
                                if (entry1.getContent().getVirtualIOServer().getPartitionState()
                                        .equals(HmcPartitionStatus.Starting.getStatus())) {
                                    Thread.sleep(1000);
                                    continue;
                                }
                                HmcPartition lpar = hmcPartitionRepository.getById(partitionId);
                                lpar.setStatus(entry1.getContent().getVirtualIOServer().getPartitionState());
                                hmcPartitionRepository.update(lpar);
                                logger.info("更新VIOS：" + partition.getName() + "的状态为"
                                        + entry.getContent().getVirtualIOServer().getPartitionState());
                                break;
                            } catch (Exception e) {
                                logger.warn("更新VIOS信息失败：", e);
                                break;
                            }
                        }
                    });
                }
            } else {
                LogicalPartitionEntry entry = (LogicalPartitionEntry) result.getData();
                hmcDatabaseHelper.updatePartition(partition, entry.getContent().getLogicalPartition(), null,
                        syncAllInfo, userId);
                // 如果当前逻辑分区的状态是正在启动，则要另外启动一个线程等待状态变化
                if (entry.getContent().getLogicalPartition().getPartitionState()
                        .equals(HmcPartitionStatus.Starting.getStatus())) {
                    logger.info("逻辑分区：" + partition.getName() + "的状态是"
                            + entry.getContent().getLogicalPartition().getPartitionState() + "，将会建立线程定期刷新该分区状态");
                    final long partitionId = partition.getId();
                    taskExecutor.submit(() -> {
                        int failedCnt = 0;
                        while (true) {
                            try {
                                BocloudResult result1 = partitionDriver.getPartitionAttribute(vendorUuid, uuid, isVios);
                                if (result1.isFailed()) {
                                    logger.warn("获取逻辑分区信息失败：" + result1.getMessage());
                                    failedCnt++;
                                    // 失败次数达到3次则放弃，否则继续尝试
                                    if (failedCnt >= 3) {
                                        break;
                                    } else {
                                        Thread.sleep(1000);
                                        continue;
                                    }
                                }
                                LogicalPartitionEntry entry1 = (LogicalPartitionEntry) result1.getData();
                                if (entry1.getContent().getLogicalPartition().getPartitionState()
                                        .equals(HmcPartitionStatus.Starting.getStatus())) {
                                    Thread.sleep(1000);
                                    continue;
                                }
                                HmcPartition lpar = hmcPartitionRepository.getById(partitionId);
                                lpar.setStatus(entry1.getContent().getLogicalPartition().getPartitionState());
                                hmcPartitionRepository.update(lpar);
                                logger.info("更新逻辑分区：" + partition.getName() + "的状态为"
                                        + entry.getContent().getLogicalPartition().getPartitionState());
                                break;
                            } catch (Exception e) {
                                logger.error("更新逻辑分区信息失败：", e);
                                break;
                            }
                        }
                    });
                }
            }
        }

        // 同步lpar的状态
        result = partitionDriver.queryPartitionRMCState(vendorUuid, partition.getUuid(), isVios);
        if (result.isFailed()) {
            if (null != operateResult) {
                operateResult.setSuccess(false);
                operateResult.setMessage(description + "任务执行成功，但是获取分区的RMC状态失败：" + result.getMessage());
            }
        } else {
            partition.setRmcState((String) result.getData());
            hmcPartitionRepository.update(partition);
        }

        // 同步更新CloudServer表
        updateCloudServerByHmcPartition(partition.getId(), userId);
    }

    public String buildHost(String url) {
        try {
            return new URL(url).getHost();
        } catch (MalformedURLException e) {
            logger.error("build host from url {} error:", url, e);
            return null;
        }
    }

    /**
     * HMC分区关闭
     *
     * @param id HMC分区ID
     * @return 操作结果
     * @author sxp
     * @since Jun 12, 2018
     */
    @Override
    public BocloudResult powerOff(Long id, RequestContext context) {
        try {
            HmcPartition partition = hmcPartitionRepository.getById(id);
            if (partition == null) {
                return new BocloudResult(false, "唯一标识为[" + id + "]的HMC分区不存在");
            }
            String status = partition.getStatus();
            if (HmcPartitionStatus.Not_Activated.getStatus().equals(status)) {
                return new BocloudResult(false, "当前分区是[未激活]状态，不能执行关闭操作");
            }

            String lparUuid = partition.getUuid();
            if (StringUtils.isEmpty(lparUuid)) {
                return new BocloudResult(false, "当前分区对应的uuid为空");
            }

            String partitionType = partition.getPartitionType();

            Long serverId = partition.getServerId();
            if (serverId == null) {
                return new BocloudResult(false, "当前分区所属的服务器唯一标识为空");
            }

            HmcServer server = hmcServerRepository.getServerById(serverId);
            if (server == null) {
                return new BocloudResult(false, "唯一标识为[" + id + "]的HMC服务器不存在");
            }

            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            if (vendor == null) {
                return new BocloudResult(false, "唯一标识为[" + server.getVendorId() + "]的云平台不存在");
            }
            String vendorUuid = vendor.getUuid();

            Boolean isVios = false;
            if (HmcPartitionType.VIOS.getType().equals(partitionType)) {
                isVios = true;
            }

            BocloudResult result = partitionDriver.powerOffPartition(vendorUuid, partition.getUuid(), isVios);
            if (result.isFailed()) {
                return new BocloudResult(false, "分区关闭失败:" + result.getMessage());
            }
            JSONObject jobJson = (JSONObject) result.getData();
            String jobId = jobJson.getString(Constant.HMC_JOB_ID);
            if (StringUtils.isEmpty(jobId)) {
                return new BocloudResult(false, "HMC分区关闭失败：生成的任务ID是空");
            }

            String description = "分区[" + partition.getName() + "]关闭";
            partition.setStatus(HmcStatus.PARTITION.POWEROFF_RUNNING.toString());
            asynGetJobStatus(partition, vendorUuid, jobId, description, context, server.getVendorId());

            return result;
        } catch (Exception e) {
            logger.error("HMC server Off fail:", e);
            return new BocloudResult(false, "分区关闭失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult restart(Long id, RequestContext context) {
        try {
            HmcPartition partition = hmcPartitionRepository.getById(id);
            if (partition == null) {
                return new BocloudResult(false, "唯一标识为[" + id + "]的HMC分区不存在");
            }
            String status = partition.getStatus();
            if (HmcPartitionStatus.Not_Activated.getStatus().equals(status)) {
                return new BocloudResult(false, "当前分区是[未激活]状态，不能执行重新启动操作");
            }

            String lparUuid = partition.getUuid();
            if (StringUtils.isEmpty(lparUuid)) {
                return new BocloudResult(false, "当前分区对应的uuid为空");
            }

            String partitionType = partition.getPartitionType();

            Long serverId = partition.getServerId();
            if (serverId == null) {
                return new BocloudResult(false, "当前分区所属的服务器唯一标识为空");
            }

            HmcServer server = hmcServerRepository.getServerById(serverId);
            if (server == null) {
                return new BocloudResult(false, "唯一标识为[" + id + "]的HMC服务器不存在");
            }

            CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
            if (vendor == null) {
                return new BocloudResult(false, "唯一标识为[" + server.getVendorId() + "]的云平台不存在");
            }
            String vendorUuid = vendor.getUuid();

            Boolean isVios = false;
            if (HmcPartitionType.VIOS.getType().equals(partitionType)) {
                isVios = true;
            }

            BocloudResult result = partitionDriver.restartPartition(vendorUuid, partition.getUuid(), isVios);
            if (result.isFailed()) {
                return new BocloudResult(false, "分区重新启动失败:" + result.getMessage());
            }
            JSONObject jobJson = (JSONObject) result.getData();
            String jobId = jobJson.getString(Constant.HMC_JOB_ID);
            if (StringUtils.isEmpty(jobId)) {
                return new BocloudResult(false, "HMC分区重新启动失败:生成的任务ID是空");
            }

            String description = "分区[" + partition.getName() + "]重新启动";
            partition.setStatus(HmcStatus.PARTITION.RESTART_RUNNING.toString());
            asynGetJobStatus(partition, vendorUuid, jobId, description, context, server.getVendorId());

            return result;
        } catch (Exception e) {
            logger.error("HMC server Off fail:", e);
            return new BocloudResult(false, "分区重新启动失败:" + e.getMessage());
        }
    }

    // 2019-08-15 : 去掉自动获取槽号的相关功能，这个接口不需要了。暂时屏蔽。 详见PBSM-5039
    // @Override
    // public BocloudResult getEmptyAdapterId(long partitionId ,List<Integer> slots)
    // {
    // try {
    // int adapterId = hmcPartitionRepository.getEmptyAdapterId(partitionId,slots);
    // return new BocloudResult(true, adapterId, "查询成功");
    // } catch (Exception e) {
    // logger.error("查询失败：", e);
    // return new BocloudResult(false, "查询失败：" + e.getMessage());
    // }
    // }

    @Override
    public BocloudResult<List<HmcVirtualDisk>> getScsiDisk(long partitionId, int adapterId) {
        try {
            List<HmcVirtualDisk> disks = hmcPartitionRepository.getScsiDisk(partitionId, adapterId);
            return new BocloudResult(true, disks, "查询成功");
        } catch (Exception e) {
            logger.error("查询失败：", e);
            return new BocloudResult(true, "查询失败");
        }
    }

    @Override
    public void updateCloudServerDiskOfLpar(long partitionId) {
        int diskCapacity = 0;
        List<HmcPartitionScsiAdapter> scsiAdapters = hmcPartitionScsiAdapterRepository.queryByPartitionId(partitionId);
        for (HmcPartitionScsiAdapter scsiAdapter : scsiAdapters) {
            List<HmcVirtualDisk> scsiDisks = hmcPartitionRepository.getScsiDisk(partitionId,
                    scsiAdapter.getAdapterId());
            for (HmcVirtualDisk scsiDisk : scsiDisks) {
                diskCapacity += scsiDisk.getDiskCapacity();
            }
        }
        HmcPartition partition = hmcPartitionRepository.getById(partitionId);
        CloudServer cloudServer = cloudServerRepository.getByUuid(partition.getUuid());
        cloudServer.setDisk(diskCapacity);
        cloudServerRepository.update(cloudServer);
    }

    @Override
    public void updateCloudServerDiskOfVios(long partitionId) {
        int diskCapacity = 0;
        List<HmcPhysicalDisk> pds = hmcPhysicalDiskRepository.query(partitionId, null);
        for (HmcPhysicalDisk pd : pds) {
            diskCapacity += pd.getVolumeCapacity();
        }
        HmcPartition partition = hmcPartitionRepository.getById(partitionId);
        CloudServer cloudServer = cloudServerRepository.getByUuid(partition.getUuid());
        cloudServer.setDisk(diskCapacity);
        cloudServerRepository.update(cloudServer);
    }

    @Override
    public BocloudResult updateCloudServerByHmcPartition(long partitionId, long contextId) {
        try {
            HmcPartition partition = hmcPartitionRepository.getById(partitionId);
            if (partition == null) {
                return new BocloudResult(false, "未找到分区");
            }
            HmcServer hmcServer = hmcServerRepository.getServerById(partition.getServerId());
            if (hmcServer == null) {
                return new BocloudResult(false, "未找到HmcServer主机");
            }
            Server server = serverRepository.getByUuid(hmcServer.getUuid());
            if (server == null) {
                return new BocloudResult(false, "未找到Server主机");
            }
            CloudVendor cloudVendor = cloudVendorRepository.query(server.getVendorId());
            if (cloudVendor == null) {
                return new BocloudResult(false, "未找到平台");
            }
            CloudServer cloudServer = cloudServerRepository.getByUuid(partition.getUuid());
            if (cloudServer == null) {
                cloudServer = new CloudServer();
                cloudServer.setCreatorId(contextId);
                cloudServer.setGmtCreate(new Date());
            } else {
                cloudServer.setGmtModify(new Date());
            }
            hmcTransportor.convertToCloudServer(partition, cloudServer, cloudVendor);
            cloudServer.setHostId(server.getId());
            cloudServer.setVendorId(cloudVendor.getId());
            cloudServer.setMenderId(contextId);
            if (cloudServer.getId() == null) {
                cloudServerRepository.save(cloudServer);
            } else {
                cloudServerRepository.update(cloudServer);
            }

            if (HmcPartitionType.VIOS.getType().equals(partition.getPartitionType())) {
                updateCloudServerDiskOfVios(partitionId);
            } else {
                updateCloudServerDiskOfLpar(partitionId);
            }

            return new BocloudResult(true, "执行成功");
        } catch (Exception e) {
            logger.error("更新失败：", e);
            return new BocloudResult(false, "更新失败");
        }
    }

    @Override
    public void updatePhysicalEthernetAdapter(HmcPartition lpar, VirtualIOServer vios) {
        List<EthernetBackingDevice> newAdapters = new ArrayList<>();
        if (vios.getSharedEthernetAdapters() != null && vios.getSharedEthernetAdapters().getAdapters() != null) {
            for (SharedEthernetAdapter seaAdapter : vios.getSharedEthernetAdapters().getAdapters()) {
                newAdapters.add(seaAdapter.getBackingDeviceChoice().getEthernetBackingDevice());
            }
        }
        if (vios.getFreeEthenetBackingDevicesForSEA() != null
                && vios.getFreeEthenetBackingDevicesForSEA().getIoAdapterChoice() != null) {
            newAdapters.add(vios.getFreeEthenetBackingDevicesForSEA().getIoAdapterChoice().getEthernetBackingDevice());
        }
        List<HmcPhysicalEthernetAdapter> oldAdapters = hmcPhysicalEthernetAdapterRepository
                .listByPartition(lpar.getId());
        List<HmcPhysicalEthernetAdapter> stillExistsAdapter = new ArrayList<>();
        for (EthernetBackingDevice newAdapter : newAdapters) {
            HmcPhysicalEthernetAdapter findedAdapter = null;
            for (HmcPhysicalEthernetAdapter oldAdapter : oldAdapters) {
                if (oldAdapter.getPhysicalLocation().equals(newAdapter.getPhysicalLocation())) {
                    findedAdapter = oldAdapter;
                    break;
                }
            }
            if (findedAdapter != null) {
                stillExistsAdapter.add(findedAdapter);
            } else {
                findedAdapter = new HmcPhysicalEthernetAdapter();
            }
            findedAdapter.setName(newAdapter.getDeviceName());
            findedAdapter.setServerId(lpar.getServerId());
            findedAdapter.setPartitionId(lpar.getId());
            findedAdapter.setDescription(newAdapter.getDescription());
            findedAdapter.setPhysicalLocation(newAdapter.getPhysicalLocation());
            findedAdapter.setDeviceType(newAdapter.getDeviceType());
            if (findedAdapter.getId() == null) {
                findedAdapter.setCreatorId(1L);
                findedAdapter.setGmtCreate(new Date());
                hmcPhysicalEthernetAdapterRepository.save(findedAdapter);
            } else {
                findedAdapter.setMenderId(1L);
                findedAdapter.setGmtModify(new Date());
                hmcPhysicalEthernetAdapterRepository.update(findedAdapter);
            }
        }
        oldAdapters.removeAll(stillExistsAdapter);
        for (HmcPhysicalEthernetAdapter oldAdapter : oldAdapters) {
            hmcPhysicalEthernetAdapterRepository.remove(HmcPhysicalEthernetAdapter.class, oldAdapter.getId());
        }
    }

    @Override
    public void updateShareEthernetAdapter(HmcPartition lpar, VirtualIOServer vios) {
        List<HmcShareEthernetAdapter> oldAdapters = hmcShareEthernetAdapterRepository.listByPartition(lpar.getId());
        if (vios.getSharedEthernetAdapters() == null || vios.getSharedEthernetAdapters().getAdapters() == null) {
            for (HmcShareEthernetAdapter oldAdapter : oldAdapters) {
                hmcShareEthernetAdapterRepository.remove(HmcShareEthernetAdapter.class, oldAdapter.getId());
            }
            return;
        }
        List<SharedEthernetAdapter> newAdapters = vios.getSharedEthernetAdapters().getAdapters();
        List<HmcShareEthernetAdapter> stillExistsAdapters = new ArrayList<>();
        for (SharedEthernetAdapter newAdapter : newAdapters) {
            HmcShareEthernetAdapter findedAdapter = null;
            for (HmcShareEthernetAdapter oldAdapter : oldAdapters) {
                if (oldAdapter.getUniqueDeviceId().equals(newAdapter.getUniqueDeviceID())) {
                    findedAdapter = oldAdapter;
                    break;
                }
            }
            if (findedAdapter != null) {
                stillExistsAdapters.add(findedAdapter);
            } else {
                findedAdapter = new HmcShareEthernetAdapter();
            }
            findedAdapter.setServerId(lpar.getServerId());
            findedAdapter.setPartitionId(lpar.getId());
            if (newAdapter.getBackingDeviceChoice() != null
                    && newAdapter.getBackingDeviceChoice().getEthernetBackingDevice() != null) {
                HmcPhysicalEthernetAdapter physicalEthernetAdapter = hmcPhysicalEthernetAdapterRepository
                        .getByPartitionAndPhysicalLocation(lpar.getId(),
                                newAdapter.getBackingDeviceChoice().getEthernetBackingDevice().getPhysicalLocation());
                if (physicalEthernetAdapter != null) {
                    findedAdapter.setPhysicalEthernetAdapterId(physicalEthernetAdapter.getId());
                } else {
                    logger.error("分区[{}]的SEA[{}]的物理以太网适配器[{}]在数据库中未找到", lpar.getName(), newAdapter.getDeviceName(),
                            newAdapter.getBackingDeviceChoice().getEthernetBackingDevice().getDeviceName());
                }
            } else {
                logger.warn("分区[{}]的SEA[{}]缺少物理以太网适配器", lpar.getName(), newAdapter.getDeviceName());
            }
            if (newAdapter.getTrunkAdapters() != null && newAdapter.getTrunkAdapters().getTrunkAdapters() != null
                    && newAdapter.getTrunkAdapters().getTrunkAdapters().size() == 1) {
                HmcPartitionNetworkAdapter partitionNetworkAdapter = hmcPartitionNetworkAdapterRepository
                        .getByPartitionIdAndAdapterId(lpar.getId(), Long.parseLong(
                                newAdapter.getTrunkAdapters().getTrunkAdapters().get(0).getVirtualSlotNumber()));
                if (partitionNetworkAdapter != null) {
                    findedAdapter.setPartitionNetworkAdapterId(partitionNetworkAdapter.getId());
                } else {
                    logger.error("分区[{}]的SEA[{}]的虚拟以太网适配器[{}]在数据库中未找到", lpar.getName(), newAdapter.getDeviceName(),
                            newAdapter.getTrunkAdapters().getTrunkAdapters().get(0).getDeviceName());
                }
            } else {
                logger.warn("分区[{}]的SEA[{}]缺少虚拟以太网适配器或虚拟以太网适配器不唯一", lpar.getName(), newAdapter.getDeviceName());
            }
            findedAdapter.setName(newAdapter.getDeviceName());
            findedAdapter.setVlanId(Integer.parseInt(newAdapter.getPortVLANID()));
            findedAdapter.setUniqueDeviceId(newAdapter.getUniqueDeviceID());
            if (newAdapter.getIpInterface() != null) {
                findedAdapter.setIp_interface_name(newAdapter.getIpInterface().getInterfaceName());
                findedAdapter.setIp_interface_status(newAdapter.getIpInterface().getState());
                findedAdapter.setIp_address(newAdapter.getIpInterface().getiPAddress());
                findedAdapter.setSubnetMask(newAdapter.getIpInterface().getSubnetMask());
            }
            if (findedAdapter.getId() == null) {
                findedAdapter.setCreatorId(1L);
                findedAdapter.setGmtCreate(new Date());
                hmcShareEthernetAdapterRepository.save(findedAdapter);
            } else {
                findedAdapter.setMenderId(1L);
                findedAdapter.setGmtModify(new Date());
                hmcShareEthernetAdapterRepository.update(findedAdapter);
            }
        }
        oldAdapters.removeAll(stillExistsAdapters);
        for (HmcShareEthernetAdapter oldAdapter : oldAdapters) {
            hmcShareEthernetAdapterRepository.remove(HmcShareEthernetAdapter.class, oldAdapter.getId());
        }
    }

    @Override
    public BocloudResult ha(HmcPartitionHaParams params, RequestContext context) {
        // worker 任务id
        String workUuid = IDFactory.instance().uuid();
        // 这是要传给worker的参数
        JSONObject workParams = new JSONObject();

        JSONObject workCallbackData = new JSONObject();
        List<HmcPartition> hmcPartitions = new ArrayList<>();
        workCallbackData.put("partitions", hmcPartitions);
        workCallbackData.put("workUuid", workUuid);
        workCallbackData.put("context", context);

        // 第一层参数
        workParams.put("timeout", 1800);
        workParams.put("response", "async");
        JSONArray targets = new JSONArray();
        workParams.put("targets", targets);
        JSONArray groups = new JSONArray();
        workParams.put("groups", groups);
        JSONObject module = new JSONObject();
        workParams.put("module", module);
        module.put("name", "aix_powerha");

        // module -- args
        JSONObject args = new JSONObject();
        module.put("args", args);
        args.put("powerha_vip", params.getFloatingIp());
        args.put("powerha_vip_netmask", params.getFloatingIpNetmask());
        args.put("cluster_name", params.getClusterName());
        args.put("app_service_name", params.getServiceName());
        args.put("shared_device", params.getShareDisk());
        if (StringUtils.isNotBlank(params.getStartCmd())) {
            args.put("start_content", params.getStartCmd());
        }
        if (StringUtils.isNotBlank(params.getStopCmd())) {
            args.put("stop_content", params.getStopCmd());
        }

        // module -- args -- node_list
        JSONArray nodeList = new JSONArray();
        args.put("node_list", nodeList);

        // module -- args -- diskhb_list
        JSONArray diskhbList = new JSONArray();
        args.put("diskhb_list", diskhbList);

        // module -- args -- node_comm_interfaces
        JSONArray nodeCommInterfaces = new JSONArray();
        args.put("node_comm_interfaces", nodeCommInterfaces);

        // module -- options
        JSONObject options = new JSONObject();
        module.put("options", options);
        options.put("become", true);

        // groups -- group
        JSONObject group = new JSONObject();
        groups.add(group);
        group.put("name", "powerha");

        // groups -- group -- hosts
        JSONArray hosts = new JSONArray();
        group.put("hosts", hosts);

        JSONArray partitions = JSON.parseArray(params.getPartitions());
        if (partitions.size() != 2) {
            return new BocloudResult(false, "参数错误");
        }

        for (int i = 0; i < partitions.size(); i++) {
            JSONObject partition = partitions.getJSONObject(i);
            if (!partition.keySet()
                    .containsAll(Arrays.asList("id", "publicIp", "port", "username", "password", "privateIps"))) {
                return new BocloudResult(false, "参数错误");
            }
            Long partitionId = partition.getLong("id");
            HmcPartition hmcPartition = hmcPartitionRepository.getById(partitionId);
            if (hmcPartition == null) {
                return new BocloudResult(false, "未找到逻辑分区");
            }
            hmcPartitions.add(hmcPartition);

            // targets -- target
            JSONObject target = new JSONObject();
            targets.add(target);
            target.put("category", "Linux");
            target.put("pasd", partition.getString("password"));
            target.put("host", partition.getString("publicIp"));
            target.put("user", partition.getString("username"));
            target.put("port", partition.getString("port"));

            // groups -- group -- hosts -- host
            JSONObject host = new JSONObject();
            hosts.add(host);
            host.put("host", partition.getString("publicIp"));

            // groups -- group -- hosts -- host -- vars
            JSONObject vars = new JSONObject();
            host.put("vars", vars);
            vars.put("alias", hmcPartition.getName());
            vars.put("is_managed", i == 0);

            // groups -- group -- hosts -- host -- vars -- ext_interfaces
            JSONArray extInterfaces = new JSONArray();
            vars.put("ext_interfaces", extInterfaces);

            // module -- args -- node_list -- node
            JSONObject node = new JSONObject();
            node.put("name", hmcPartition.getName());
            node.put("value", hmcPartition.getName() + "_en1");
            nodeList.add(node);

            // module -- args -- diskhb_list -- diskhb
            JSONObject diskhb = new JSONObject();
            diskhb.put("node_name", hmcPartition.getName());
            diskhb.put("diskhb_name", hmcPartition.getName() + "hb");
            diskhb.put("diskhb_device", params.getShareDisk());
            diskhbList.add(diskhb);

            // module -- args -- node_comm_interfaces -- node_comm_interface
            JSONObject nodeCommInterface1 = new JSONObject();
            nodeCommInterface1.put("node_name", hmcPartition.getName());
            nodeCommInterface1.put("interface", hmcPartition.getName() + "_en1");
            nodeCommInterfaces.add(nodeCommInterface1);
            JSONObject nodeCommInterface2 = new JSONObject();
            nodeCommInterface2.put("node_name", hmcPartition.getName());
            nodeCommInterface2.put("interface", hmcPartition.getName() + "_en2");
            nodeCommInterfaces.add(nodeCommInterface2);

            JSONArray privateIps = partition.getJSONArray("privateIps");
            if (privateIps.size() != 2) {
                return new BocloudResult(false, "参数错误");
            }
            for (int j = 0; j < privateIps.size(); j++) {
                JSONObject privateIp = privateIps.getJSONObject(j);
                if (!privateIp.keySet().containsAll(Arrays.asList("ip", "netmask", "gateway"))) {
                    return new BocloudResult(false, "参数错误");
                }
                // groups -- group -- hosts -- host -- vars -- ext_interfaces -- ext_interface
                JSONObject extInterface = new JSONObject();
                extInterfaces.add(extInterface);
                extInterface.put("interface", "en" + (j + 1));
                extInterface.put("netaddr", privateIp.getString("ip"));
                extInterface.put("netmask", privateIp.getString("netmask"));
                extInterface.put("gateway", privateIp.getString("gateway"));
            }

        }
        logger.info("invoke worker params: {}", workParams.toJSONString());
        BocloudResult result = requestWorker.invoke(workParams, this::haWorkerCallback, workCallbackData);
        if (result.isFailed()) {
            return result;
        }
        return new BocloudResult(true, "任务已经下发，正在执行...");
    }

    @Override
    public BocloudResult createVG(HmcPartitionCreateVGParams params, RequestContext context) {
        // ppSize 需要是2的指数倍
        long ppSize = params.getPpSize();
        if (ppSize <= 0 || (ppSize & (ppSize - 1)) != 0) {
            return new BocloudResult(false, "PP尺寸需要是2的指数倍");
        }

        Long partitionId = params.getPartitionId();
        HmcPartition hmcPartition = hmcPartitionRepository.getById(partitionId);
        if (hmcPartition == null) {
            return new BocloudResult(false, "未找到逻辑分区");
        }

        // worker 任务id
        String workUuid = IDFactory.instance().uuid();
        // 这是要传给worker的参数
        JSONObject workParams = new JSONObject();
        JSONObject workCallbackData = new JSONObject();
        // 第一层参数
        JSONArray targets = new JSONArray();
        workParams.put("targets", targets);
        JSONObject module = new JSONObject();
        module.put("name", "aix_disk");
        workParams.put("module", module);

        // targets -- target
        JSONObject target = new JSONObject();
        targets.add(target);
        target.put("category", "Linux");
        target.put("host", params.getPublicIp());
        target.put("port", params.getPort());
        target.put("user", params.getUsername());
        target.put("pasd", params.getPassword());

        // module -- args
        JSONObject args = new JSONObject();
        module.put("args", args);

        // module -- args -- lvg
        JSONObject lvg = new JSONObject();
        args.put("lvg", lvg);
        lvg.put("force", "yes");
        lvg.put("state", "present");
        lvg.put("vg", params.getVgName());
        lvg.put("pvs", "[" + params.getDisks() + "]");
        lvg.put("vg_type", params.getVgType());
        lvg.put("pp_size", params.getPpSize().intValue());

        // module -- options·
        JSONObject options = new JSONObject();
        module.put("options", options);
        options.put("become", true);

        workCallbackData.put("partitionName", hmcPartition.getName());
        workCallbackData.put("vgName", params.getVgName());
        workCallbackData.put("context", context);

        logger.info("invoke worker params: {}", workParams.toJSONString());
        BocloudResult result = requestWorker.invoke(workParams, this::createVGWorkerCallback, workCallbackData);
        if (result.isFailed()) {
            return result;
        }
        return new BocloudResult(true, "任务已经下发，正在执行...");
    }

    @Override
    public BocloudResult createLV(HmcPartitionCreateLVParams params, RequestContext context) {
        Long partitionId = params.getPartitionId();
        HmcPartition hmcPartition = hmcPartitionRepository.getById(partitionId);
        if (hmcPartition == null) {
            return new BocloudResult(false, "未找到逻辑分区");
        }

        // worker 任务id
        String workUuid = IDFactory.instance().uuid();
        // 这是要传给worker的参数
        JSONObject workParams = new JSONObject();
        JSONObject workCallbackData = new JSONObject();
        // 第一层参数
        JSONArray targets = new JSONArray();
        workParams.put("targets", targets);
        JSONObject module = new JSONObject();
        module.put("name", "aix_disk");
        workParams.put("module", module);

        // targets -- target
        JSONObject target = new JSONObject();
        targets.add(target);
        target.put("category", "Linux");
        target.put("host", params.getPublicIp());
        target.put("port", params.getPort());
        target.put("user", params.getUsername());
        target.put("pasd", params.getPassword());

        // module -- args
        JSONObject args = new JSONObject();
        module.put("args", args);

        // module -- args -- lvol
        JSONObject lvol = new JSONObject();
        args.put("lvol", lvol);
        lvol.put("vg", params.getVgName());
        lvol.put("lv", params.getLvName());
        lvol.put("size", params.getSize() + "M");

        String mount = params.getMount().startsWith("/") ? params.getMount()
                : "/" + params.getMount();
        // module -- args -- file_system
        JSONObject fileSystem = new JSONObject();
        args.put("file_system", fileSystem);
        fileSystem.put("device", params.getLvName());
        fileSystem.put("filesystem", mount);
        fileSystem.put("state", "present");

        // module -- args -- file_system_mounted
        JSONObject fileSystemMounted = new JSONObject();
        args.put("file_system_mounted", fileSystemMounted);
        fileSystemMounted.put("device", params.getLvName());
        fileSystemMounted.put("filesystem", mount);
        fileSystemMounted.put("state", "mounted");

        // module -- options
        JSONObject options = new JSONObject();
        module.put("options", options);
        options.put("become", true);

        workCallbackData.put("partitionName", hmcPartition.getName());
        workCallbackData.put("lvName", params.getLvName());
        workCallbackData.put("context", context);

        logger.info("invoke worker params: {}", workParams.toJSONString());
         BocloudResult result = requestWorker.invoke(workParams, this::createLVWorkerCallback, workCallbackData);
        if (result.isFailed()) {
            return result;
        }
        return new BocloudResult(true, "任务已经下发，正在执行...");
    }

    @Override
    public BocloudResult removeVG(HmcPartitionRemoveVGParams params, RequestContext context) {
        Long partitionId = params.getPartitionId();
        HmcPartition hmcPartition = hmcPartitionRepository.getById(partitionId);
        if (hmcPartition == null) {
            return new BocloudResult(false, "未找到逻辑分区");
        }

        // worker 任务id
        String workUuid = IDFactory.instance().uuid();
        // 这是要传给worker的参数
        JSONObject workParams = new JSONObject();
        JSONObject workCallbackData = new JSONObject();
        // 第一层参数
        JSONArray targets = new JSONArray();
        workParams.put("targets", targets);
        JSONObject module = new JSONObject();
        module.put("name", "aix_disk");
        workParams.put("module", module);

        // targets -- target
        JSONObject target = new JSONObject();
        targets.add(target);
        target.put("category", "Linux");
        target.put("host", params.getPublicIp());
        target.put("port", params.getPort());
        target.put("user", params.getUsername());
        target.put("pasd", params.getPassword());

        // module -- args
        JSONObject args = new JSONObject();
        module.put("args", args);

        // module -- args -- lvg
        JSONObject lvg = new JSONObject();
        args.put("lvg", lvg);
        lvg.put("state", "absent");
        lvg.put("vg", params.getVgName());

        // module -- options
        JSONObject options = new JSONObject();
        module.put("options", options);
        options.put("become", true);

        workCallbackData.put("partitionName", hmcPartition.getName());
        workCallbackData.put("vgName", params.getVgName());
        workCallbackData.put("context", context);

        logger.info("invoke worker params: {}", workParams.toJSONString());
        BocloudResult result = requestWorker.invoke(workParams, this::removeVGWorkerCallback, workCallbackData);
        if (result.isFailed()) {
            return result;
        }
        return new BocloudResult(true, "任务已经下发，正在执行...");
    }

    @Override
    public BocloudResult removeLV(HmcPartitionRemoveLVParams params, RequestContext context) {
        Long partitionId = params.getPartitionId();
        HmcPartition hmcPartition = hmcPartitionRepository.getById(partitionId);
        if (hmcPartition == null) {
            return new BocloudResult(false, "未找到逻辑分区");
        }

        // worker 任务id
        String workUuid = IDFactory.instance().uuid();
        // 这是要传给worker的参数
        JSONObject workParams = new JSONObject();
        JSONObject workCallbackData = new JSONObject();
        // 第一层参数
        JSONArray targets = new JSONArray();
        workParams.put("targets", targets);
        JSONObject module = new JSONObject();
        module.put("name", "aix_disk");
        workParams.put("module", module);

        // targets -- target
        JSONObject target = new JSONObject();
        targets.add(target);
        target.put("category", "Linux");
        target.put("host", params.getPublicIp());
        target.put("port", params.getPort());
        target.put("user", params.getUsername());
        target.put("pasd", params.getPassword());

        // module -- args
        JSONObject args = new JSONObject();
        module.put("args", args);

        // module -- args -- lvol
        JSONObject lvol = new JSONObject();
        args.put("lvol", lvol);
        lvol.put("vg", params.getVgName());
        lvol.put("lv", params.getLvName());

        String mount = params.getMount().startsWith("/") ? params.getMount()
                : "/" + params.getMount();
        // module -- args -- file_system
        JSONObject fileSystem = new JSONObject();
        args.put("file_system", fileSystem);
        fileSystem.put("device", params.getLvName());
        fileSystem.put("filesystem", mount);
        fileSystem.put("state", "absent");

        // module -- args -- file_system_unmounted
        JSONObject fileSystemUnmounted = new JSONObject();
        args.put("file_system_unmounted", fileSystemUnmounted);
        fileSystemUnmounted.put("device", params.getLvName());
        fileSystemUnmounted.put("filesystem", mount);
        fileSystemUnmounted.put("state", "unmounted");

        // module -- options
        JSONObject options = new JSONObject();
        module.put("options", options);
        options.put("become", true);

        workCallbackData.put("partitionName", hmcPartition.getName());
        workCallbackData.put("lvName", params.getLvName());
        workCallbackData.put("context", context);

        logger.info("invoke worker params: {}", workParams.toJSONString());
        BocloudResult result = requestWorker.invoke(workParams, this::removeLVWorkerCallback, workCallbackData);
        if (result.isFailed()) {
            return result;
        }
        return new BocloudResult(true, "任务已经下发，正在执行...");
    }

    public void haWorkerCallback(Map<String, Object> callbackData, BocloudResult workerResult) {
        StringBuilder partitionNames = new StringBuilder();

        List<HmcPartition> hmcPartitions = (List<HmcPartition>) callbackData.get("partitions");
        for (HmcPartition hmcPartition : hmcPartitions) {
            partitionNames.append(hmcPartition.getName()).append(", ");
        }
        partitionNames = new StringBuilder(partitionNames.substring(0, partitionNames.length() - 2));

        logger.debug("Powervc HA[{}] result: {}", partitionNames.toString(), JSON.toJSONString(workerResult));
        String sockerMessage = "创建分区HA[" + partitionNames + "]";
        if (workerResult.isSuccess()) {
            sockerMessage += "成功";
        } else {
            sockerMessage += "失败：\r\n" + workerResult.getMessage();
        }

        RequestContext context = (RequestContext) callbackData.get("context");

        OperateResult result = new OperateResult(workerResult.isSuccess(), sockerMessage, "hmc.ha", null,
                OperateCategory.ResourceEvent, context);
        resourceEventPublisher.send(result);

        NotifyMessage notifyMessage = new NotifyMessage(context, "创建分区HA通知", sockerMessage, null, true, false);
        amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
    }

    public void createVGWorkerCallback(Map<String, Object> callbackData, BocloudResult workerResult) {
        String partitionName = (String) callbackData.get("partitionName");
        String vgName = (String) callbackData.get("vgName");
        RequestContext context = (RequestContext) callbackData.get("context");
        boolean success;
        String sockerMessage = "为逻辑分区[" + partitionName + "]创建逻辑卷组[" + vgName + "]";
        if (workerResult.isSuccess()) {
            Optional<JSONObject> msgObject = Optional.ofNullable(workerResult.getData()).map(Object::toString)
                    .map(JSON::parseArray)
                    .map(o -> o.stream().findFirst().map(JSON::toJSONString).map(JSON::parseObject).orElse(null))
                    .map(o -> o.getJSONObject("message"));
            success = msgObject.map(o -> o.getBoolean("changed")).orElse(true);
            sockerMessage += success ? "成功" : ("失败：\n\n" + msgObject.map(o -> o.getString("msg")).orElse(""));
        } else {
            success = false;
            sockerMessage += "失败：\r\n" + workerResult.getMessage();
        }
        OperateResult result = new OperateResult(success, sockerMessage, "hmc.lpar.createVG", null,
                OperateCategory.ResourceEvent, context);
        resourceEventPublisher.send(result);

        NotifyMessage notifyMessage = new NotifyMessage(context, "为逻辑分区创建逻辑卷组通知", sockerMessage, null, true, false);
        amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
    }

    public void createLVWorkerCallback(Map<String, Object> callbackData, BocloudResult workerResult) {
        String partitionName = (String) callbackData.get("partitionName");
        String lvName = (String) callbackData.get("lvName");
        RequestContext context = (RequestContext) callbackData.get("context");
        String sockerMessage = "为逻辑分区[" + partitionName + "]创建逻辑卷[" + lvName + "]";
        if (workerResult.isSuccess()) {
            sockerMessage += "成功";
        } else {
            sockerMessage += "失败：\r\n" + workerResult.getMessage();
        }
        OperateResult result = new OperateResult(workerResult.isSuccess(), sockerMessage, "hmc.lpar.createLV", null,
                OperateCategory.ResourceEvent, context);
        resourceEventPublisher.send(result);

        NotifyMessage notifyMessage = new NotifyMessage(context, "为逻辑分区创建逻辑卷通知", sockerMessage, null, true, false);
        amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
    }

    public void removeVGWorkerCallback(Map<String, Object> callbackData, BocloudResult workerResult) {
        String partitionName = (String) callbackData.get("partitionName");
        String vgName = (String) callbackData.get("vgName");
        RequestContext context = (RequestContext) callbackData.get("context");
        String sockerMessage = "为逻辑分区[" + partitionName + "]删除逻辑卷组[" + vgName + "]";
        if (workerResult.isSuccess()) {
            sockerMessage += "成功";
        } else {
            sockerMessage += "失败：\r\n" + workerResult.getMessage();
        }
        OperateResult result = new OperateResult(workerResult.isSuccess(), sockerMessage, "hmc.lpar.removeVG", null,
                OperateCategory.ResourceEvent, context);
        resourceEventPublisher.send(result);

        NotifyMessage notifyMessage = new NotifyMessage(context, "为逻辑分区删除逻辑卷组通知", sockerMessage, null, true, false);
        amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
    }

    public void removeLVWorkerCallback(Map<String, Object> callbackData, BocloudResult workerResult) {
        String partitionName = (String) callbackData.get("partitionName");
        String lvName = (String) callbackData.get("lvName");
        RequestContext context = (RequestContext) callbackData.get("context");
        String sockerMessage = "为逻辑分区[" + partitionName + "]删除逻辑卷[" + lvName + "]";
        if (workerResult.isSuccess()) {
            sockerMessage += "成功";
        } else {
            sockerMessage += "失败：\r\n" + workerResult.getMessage();
        }
        OperateResult result = new OperateResult(workerResult.isSuccess(), sockerMessage, "hmc.lpar.removeLV", null,
                OperateCategory.ResourceEvent, context);
        resourceEventPublisher.send(result);

        NotifyMessage notifyMessage = new NotifyMessage(context, "为逻辑分区删除逻辑卷通知", sockerMessage, null, true, false);
        amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
    }

}
