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

import com.bocloud.cmp.model.hmc.sdk.module.*;
import com.bocloud.common.model.SimpleBean;
import com.bocloud.ims.common.enums.HmcStatus;
import com.bocloud.ims.entity.resource.hmc.*;
import com.bocloud.ims.interfaces.resource.hmc.HmcPartitionService;
import com.bocloud.ims.repository.resource.hmc.*;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Service("hmcDatabaseHelper")
public class HmcDatabaseHelper {
    private static Logger logger = LoggerFactory.getLogger(HmcDatabaseHelper.class);
    @Autowired
    private HmcPartitionRepository hmcPartitionRepository;
    @Autowired
    private HmcProfileRepository hmcProfileRepository;
    @Autowired
    private HmcPartitionScsiAdapterRepository hmcPartitionScsiAdapterRepository;
    @Autowired
    private HmcVolumeGroupRepository hmcVolumeGroupRepository;
    @Autowired
    private HmcVirtualDiskRepository hmcVirtualDiskRepository;
    @Autowired
    private HmcVirtualCdRepository hmcVirtualCdRepository;
    @Autowired
    private HmcPhysicalDiskRepository hmcPhysicalDiskRepository;
    @Autowired
    private HmcProfileIoslotRepository hmcProfileIoslotRepository;
    @Autowired
    private HmcProfileNetworkAdapterRepository hmcProfileNetworkAdapterRepository;
    @Autowired
    private HmcProfileScsiAdapterRepository hmcProfileScsiAdapterRepository;
    @Autowired
    private HmcProfileFibreAdapterRepository hmcProfileFibreAdapterRepository;
    @Autowired
    private HmcHostEthernetAdapterRepository hmcHostEthernetAdapterRepository;
    @Autowired
    private HmcHeaLogicalPortRepository hmcHeaLogicalPortRepository;
    @Autowired
    private HmcHeaPhysicalPortRepository hmcHeaPhysicalPortRepository;
    @Autowired
    private HmcProfileLheaRepository hmcProfileLheaRepository;
    @Autowired
    private HmcVirtualSwitchRepository hmcVirtualSwitchRepository;
    @Autowired
    private HmcIoAdapterRepository hmcIoAdapterRepository;
    @Autowired
    private HmcIoBusRepository hmcIoBusRepository;
    @Autowired
    private HmcIplConfigRepository hmcIplConfigRepository;
    @Autowired
    private HmcSystemMemoryConfigRepository hmcSystemMemoryConfigRepository;
    @Autowired
    private HmcSystemProcessorConfigRepository hmcSystemProcessorConfigRepository;
    @Autowired
    private HmcSystemCapabilityRepository hmcSystemCapabilityRepository;
    @Autowired
    private HmcServerRepository hmcServerRepository;
    @Autowired
    private HmcPhysicalFibreChannelRepository hmcPhysicalFibreChannelRepository;
    @Autowired
    private HmcVirtualFibreChannelMappingRepository hmcVirtualFibreChannelMappingRepository;
    @Autowired
    private HmcPartitionVfcAdapterRepository hmcPartitionVfcAdapterRepository;
    @Autowired
    private HmcPartitionService hmcPartitionService;
    @Autowired
    private HmcSystemSharedProcessorPoolRepository sharedProcessorPoolRepository;
    @Autowired
    private HmcPartitionProcessorRepository partitionProcessorRepository;
    @Autowired
    private HmcPartitionMemoryRepository partitionMemoryRepository;
    @Autowired
    private HmcPartitionIoRepository partitionIoRepository;

    @Transactional
    public void syncLparProfiles(HmcPartition par, List<LogicalPartitionProfileEntry> profileEntrys,
                                 String activeProfile, Long userId) {
        if (null == profileEntrys) {
            return;
        }
        try {
            // 获取分区概要文件列表数据
            List<HmcProfile> profiles = hmcProfileRepository.listByPartitionId(par.getId());
            Map<String, HmcProfile> oldProfileMap = Maps.newHashMap();
            for (HmcProfile profile : profiles) {
                oldProfileMap.put(profile.getUuid(), profile);
            }

            // 更新或插入新的Lpar profile记录
            for (LogicalPartitionProfileEntry entry : profileEntrys) {
                HmcProfile convertProfile = null;
                // 查看这个概要文件是否是这个分区的活动概要文件
                Boolean isActiveProfile = false;
                if (null != activeProfile && activeProfile.equals(entry.getId())) {
                    isActiveProfile = true;
                }
                if (oldProfileMap.containsKey(entry.getId())) {
                    // 更新Lpar profile记录
                    convertProfile = oldProfileMap.get(entry.getId());
                    convertProfile.setServerId(par.getServerId());
                    convertToHmcLparProfile(convertProfile, entry);
                    convertProfile.setIsActiveProfile(isActiveProfile);
                    convertProfile.setMenderId(userId);
                    convertProfile.setGmtModify(new Date());
                    hmcProfileRepository.update(convertProfile);
                    oldProfileMap.remove(entry.getId());
                } else {
                    // 插入Lpar profile记录
                    convertProfile = new HmcProfile();
                    convertProfile.setServerId(par.getServerId());
                    convertToHmcLparProfile(convertProfile, entry);
                    convertProfile.setIsActiveProfile(isActiveProfile);
                    convertProfile.preSave(userId, userId, par.getId());
                    hmcProfileRepository.save(convertProfile);
                }

                // 插入新的概要文件IOConfiguration设置
                LogicalPartitionProfile profile = entry.getContent().getLogicalPartitionProfile();
                if (null != profile.getIoConfigurationInstance()) {
                    syncIOConfiguration(convertProfile.getId(), profile.getIoConfigurationInstance());
                }

                // 插入新的概要文件LHEA设置
                if (null != profile.getHostEthernetAdapterLogicalPorts()) {
                    syncProfileHeaLogicalPorts(convertProfile.getId(), profile.getHostEthernetAdapterLogicalPorts().getHostEthernetAdapterLogicalPortList());
                }
            }

            // 删除在HMC上已经不存在的概要文件
            Iterator<HmcProfile> iteratorProfile = oldProfileMap.values().iterator();
            while (iteratorProfile.hasNext()) {
                Long id = iteratorProfile.next().getId();
                hmcProfileRepository.remove(id, userId);
            }
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Update hmc_lpar_profile table failure. Error message:" + e.getMessage(), e);
        }
    }

    @Transactional
    public void syncVirutalStorage(HmcPartition vios, List<VolumeGroupEntry> entries,
                                   List<VirtualSCSIMapping> mappings) {
        try {
            if (entries == null) {
                logger.warn("volume group is empty");
                return;
            }
            if (entries.size() == 0) {
                logger.warn("volume group is empty");
            }

            // 删除当前平台下的虚拟磁盘和卷组
            hmcVirtualDiskRepository.delete(vios.getId());
            hmcVirtualCdRepository.delete(vios.getId());
            hmcVolumeGroupRepository.delete(vios.getId());

            for (VolumeGroupEntry entry : entries) {
                HmcVolumeGroup vg = new HmcVolumeGroup();
                vg.setAvailableSize(stringToDouble(entry.getContent().getVolumeGroup().getAvailableSize()));
                vg.setFreeSpace(stringToDouble(entry.getContent().getVolumeGroup().getFreeSpace()));
                vg.setGroupCapacity(stringToDouble(entry.getContent().getVolumeGroup().getGroupCapacity()));
                vg.setGroupName(entry.getContent().getVolumeGroup().getGroupName());
                vg.setViosId(vios.getId());
                vg.setGroupSerialId(entry.getContent().getVolumeGroup().getGroupSerialID());
                vg.setMaxLogicalVolumes(Long.parseLong(entry.getContent().getVolumeGroup().getMaximumLogicalVolumes()));
                vg.setUuid(entry.getContent().getVolumeGroup().getMetadata().getAtom().getAtomId());
                hmcVolumeGroupRepository.save(vg);

                List<VirtualDisk> virtualDisks = Optional.of(entry)
                        .map(VolumeGroupEntry::getContent)
                        .map(VolumeGroupContent::getVolumeGroup)
                        .map(VolumeGroup::getVirtualDisks)
                        .map(VirtualDisks::getDisks)
                        .orElse(new ArrayList<>());
                for (VirtualDisk vd : virtualDisks) {
                    HmcVirtualDisk virtualDisk = new HmcVirtualDisk();
                    virtualDisk.setDiskCapacity(stringToDouble(vd.getDiskCapacity()));
                    virtualDisk.setDiskLabel(vd.getDiskLabel());
                    virtualDisk.setDiskName(vd.getDiskName());
                    virtualDisk.setUniqueDeviceId(vd.getUniqueDeviceID());
                    virtualDisk.setVgId(vg.getId());
                    virtualDisk.setViosId(vios.getId());
                    virtualDisk.setStatus(HmcStatus.DISK.NORMAL.name());
                    if (mappings != null) {
                        for (VirtualSCSIMapping mapping : mappings) {
                            if (mapping.getStorage() != null && mapping.getStorage().getVirtualDisk() != null) {
                                if (vd.getDiskName() != null && vd.getDiskName().equals(mapping.getStorage().getVirtualDisk().getDiskName())) {
                                    if (mapping.getServerAdapter() != null
                                            // && mapping.getServerAdapter().getRemoteLogicalPartitionId() != null 去掉这个条件，有可能是任意分区
                                            // && mapping.getServerAdapter().getRemoteSlotNumber() != null 去掉这个条件，有可能是任意插槽
                                            && mapping.getServerAdapter().getLocalPartitionId() != null
                                            && mapping.getServerAdapter().getVirtualSlotNumber() != null) {
                                        virtualDisk.setViosSlotId(stringToInt(mapping.getServerAdapter().getVirtualSlotNumber()));
                                        Optional.ofNullable(mapping.getServerAdapter().getRemoteLogicalPartitionId())
                                                .map(Integer::parseInt)
                                                .map(remoteLogicalPartitionId -> hmcPartitionRepository.get(remoteLogicalPartitionId, vios.getServerId()))
                                                .map(HmcPartition::getId)
                                                .ifPresent(virtualDisk::setAssignPartitionId);
                                        Optional.ofNullable(mapping.getServerAdapter().getRemoteSlotNumber())
                                                .map(Integer::parseInt)
                                                .ifPresent(virtualDisk::setAssignSlotId);
                                    }
                                }
                            }
                        }
                    }
                    hmcVirtualDiskRepository.save(virtualDisk);
                }

                List<VirtualOpticalMedia> virtualOpticalMedias = Optional.of(entry)
                        .map(VolumeGroupEntry::getContent)
                        .map(VolumeGroupContent::getVolumeGroup)
                        .map(VolumeGroup::getMediaRepositories)
                        .map(MediaRepositories::getVirtualMediaRepository)
                        .map(VirtualMediaRepository::getOpticalMedia)
                        .map(OpticalMedia::getVirtualOpticalMediaList)
                        .orElse(new ArrayList<>());
                for (VirtualOpticalMedia cd : virtualOpticalMedias) {
                    HmcVirtualCd virtualCd = new HmcVirtualCd();
                    virtualCd.setUuid(cd.getMediaUDId());
                    virtualCd.setCdName(cd.getMediaName());
                    virtualCd.setMountType(cd.getMountType());
                    virtualCd.setViosId(vios.getId());
                    Optional.ofNullable(cd.getSize()).map(Double::parseDouble).ifPresent(virtualCd::setCdSize);
                    if (mappings != null) {
                        for (VirtualSCSIMapping mapping : mappings) {
                            if (mapping.getStorage() != null && mapping.getStorage().getVirtualOpticalMedia() != null) {
                                if (cd.getMediaName() != null && cd.getMediaName()
                                        .equals(mapping.getStorage().getVirtualOpticalMedia().getMediaName())) {
                                    if (mapping.getServerAdapter() != null
                                            && mapping.getServerAdapter().getRemoteLogicalPartitionId() != null
                                            // && mapping.getServerAdapter().getRemoteSlotNumber() != null 去掉这个条件，有可能是任意插槽
                                            && mapping.getServerAdapter().getLocalPartitionId() != null
                                            && mapping.getServerAdapter().getVirtualSlotNumber() != null) {
                                        HmcPartition hmcPartition = hmcPartitionRepository.get(
                                                stringToInt(mapping.getServerAdapter().getRemoteLogicalPartitionId()),
                                                vios.getServerId()
                                        );
                                        if(hmcPartition!=null){
                                            virtualCd.setAssignPartitionId(hmcPartition.getId());
                                        }
                                        Optional.ofNullable(mapping.getServerAdapter().getRemoteSlotNumber()).map(Integer::parseInt).ifPresent(virtualCd::setAssignPartitionSlot);
                                        virtualCd.setViosSlot(stringToInt(mapping.getServerAdapter().getVirtualSlotNumber()));
                                    }
                                }
                            }
                        }
                    }
                    hmcVirtualCdRepository.save(virtualCd);
                }
            }
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("sync virutal storage info exception:", e);
        }
    }

    @Transactional
    public void syncPhysicalDisk(HmcPartition vios, List<PhysicalVolume> entries, List<VirtualSCSIMapping> mappings,
                                 List<VolumeGroupEntry> vgEntries) {
        try {
            if (entries == null) {
                logger.warn("physical disk is empty");
                return;
            }
            if (entries.size() == 0) {
                logger.warn("physical disk is empty");
            }

            // 删除当前平台下的物理磁盘
            hmcPhysicalDiskRepository.delete(vios.getId(), null);

            for (PhysicalVolume entry : entries) {
                HmcPhysicalDisk pd = new HmcPhysicalDisk();
                pd.setViosId(vios.getId());
                pd.setAvailable(Boolean.parseBoolean(entry.getAvailableForUsage()));
                pd.setDescription(entry.getDescription());
                pd.setIsFc(Boolean.parseBoolean(entry.getIsFibreChannelBacked()));
                pd.setLocationCode(entry.getLocationCode());
                pd.setReservePolicy(entry.getReservePolicy());
                pd.setReservePolicyAlgorithm(entry.getReservePolicyAlgorithm());
                pd.setUniqueDeviceId(entry.getUniqueDeviceId());
                pd.setVolumeCapacity(BigDecimal.valueOf(stringToInt(entry.getVolumeCapacity()))
                        .divide(BigDecimal.valueOf(1024), 2, RoundingMode.HALF_UP).doubleValue()
                );
                pd.setVolumeName(entry.getVolumeName());
                pd.setVolumeState(entry.getVolumeState());
                if (mappings != null) {
                    for (VirtualSCSIMapping mapping : mappings) {
                        if (entry.getVolumeName() != null && entry.getVolumeName().equals(mapping.getServerAdapter().getBackingDeviceName())) {
                            HmcPartition hmcPartition = this.hmcPartitionRepository.get(
                                stringToInt(mapping.getServerAdapter().getRemoteLogicalPartitionId()), vios.getServerId()
                            );
                            Optional.ofNullable(mapping.getServerAdapter()).map(ServerAdapter::getRemoteSlotNumber)
                                    .map(Integer::parseInt).ifPresent(pd::setAssignSlotId);
                            pd.setAssignPartitionId(hmcPartition == null ? null : hmcPartition.getId());
                            pd.setViosSlotId(stringToInt(mapping.getServerAdapter().getVirtualSlotNumber()));
                        }
                    }
                }
                if (vgEntries != null) {
                    for (VolumeGroupEntry vg : vgEntries) {
                        if (vg.getContent().getVolumeGroup().getPhysicalVolumes() != null &&
                            vg.getContent().getVolumeGroup().getPhysicalVolumes().getPhysicalVolumeList() != null) {
                            for (PhysicalVolume vgPv : vg.getContent().getVolumeGroup().getPhysicalVolumes().getPhysicalVolumeList()) {
                                if (entry.getVolumeName().equals(vgPv.getVolumeName())) {
                                    List<HmcVolumeGroup> vgs = hmcVolumeGroupRepository.query(vios.getId(), vg.getContent().getVolumeGroup().getGroupName());
                                    if (vgs.size() == 0) {
                                        continue;
                                    } else {
                                        pd.setVgId(vgs.get(0).getId());
                                    }
                                }
                            }
                        }
                    }
                }
                hmcPhysicalDiskRepository.save(pd);
            }
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("sync physical storage info exception:", e);
        }
    }

    public void syncIOConfiguration(Long profileId, IOConfigurationInstance ioConfig) throws Exception {
        if (null == ioConfig) {
            return;
        }
        // io slot设置
        syncProfileIoslot(profileId, ioConfig.getProfileIoSlots());

        // virtual Adapter设置
        if (null != ioConfig.getProfileVirtualIoAdapters()) {
            syncAdapter(profileId, ioConfig.getProfileVirtualIoAdapters().getSubclasses());
        }
    }

    public void syncProfileHeaLogicalPorts(Long profileId, List<HostEthernetAdapterLogicalPort> heaLogicalPorts) throws Exception {
        if (null == heaLogicalPorts || heaLogicalPorts.isEmpty()) {
            hmcProfileLheaRepository.deleteByProfileId(profileId);
            return;
        }
        List<HmcProfileLhea> hmcProfileLheas = hmcProfileLheaRepository.queryByProfileId(profileId);
        Map<String, HmcProfileLhea> hmcProfileLheaMap = new HashMap<>();
        for (HmcProfileLhea hmcProfileLhea : hmcProfileLheas) {
            // 2019-09-21 : 现在来看，portGroupId和physicalPortId联合起来标识唯一一个数据
            hmcProfileLheaMap.put("#" + hmcProfileLhea.getPortGroupId() + "#-@" + hmcProfileLhea.getPhysicalPortId() + "@", hmcProfileLhea);
        }
        for (HostEthernetAdapterLogicalPort logicalPort : heaLogicalPorts) {
            String key = "#" + logicalPort.getPortGroupID() + "#-@" + logicalPort.getPhysicalPortID() + "@";

            HmcProfileLhea lhea = hmcProfileLheaMap.get(key) == null ? new HmcProfileLhea() : hmcProfileLheaMap.get(key);
            lhea.setProfileId(profileId);
            lhea.setAdapterId(Long.parseLong(logicalPort.getAdapterID()));
            lhea.setLogicalPortId(stringToInt(logicalPort.getLogicalPortID()));
            lhea.setPhysicalPortId(stringToInt(logicalPort.getPhysicalPortID()));
            lhea.setAllowVlanIds(logicalPort.getAllowedVLANIDs());
            lhea.setAllowMacAddresses(logicalPort.getAllowedOSMACAddresses());
            lhea.setPortGroupId(stringToInt(logicalPort.getPortGroupID()));
            if (lhea.getId() == null) {
                hmcProfileLheaRepository.save(lhea);
            } else {
                hmcProfileLheaRepository.updateEntity(lhea);
            }
            hmcProfileLheaMap.remove(key);
        }
        for (HmcProfileLhea hmcProfileLhea : hmcProfileLheaMap.values()) {
            hmcProfileLheaRepository.delete(hmcProfileLhea);
        }
    }

    private void syncProfileIoslot(Long profileId, ProfileIOSlots newProfileIOSlots) throws Exception {
        if (newProfileIOSlots == null || newProfileIOSlots.getProfileIOSlot() == null || newProfileIOSlots.getProfileIOSlot().size() == 0) {
            hmcProfileIoslotRepository.deleteByProfileId(profileId);
            return;
        }
        // 先查询一下旧数据
        List<HmcProfileIoslot> oldProfileIOSlots = hmcProfileIoslotRepository.queryByProfileId(profileId);
        Map<Long, HmcProfileIoslot> oldProfileIOSlotMap = new HashMap<>();
        for (HmcProfileIoslot oldProfileIOSlot : oldProfileIOSlots) {
            oldProfileIOSlotMap.put(oldProfileIOSlot.getAdapterId(), oldProfileIOSlot);
        }
        for (ProfileIOSlot newProfileIOSlot : newProfileIOSlots.getProfileIOSlot()) {
            long adapterId = Long.parseLong(
                newProfileIOSlot.getAssociatedIOSlot().getRelatedIOAdapter().getIoAdapter().getAdapterID()
            );
            HmcProfileIoslot hmcProfileIoslot =
                oldProfileIOSlotMap.get(adapterId) == null ? new HmcProfileIoslot() : oldProfileIOSlotMap.get(adapterId);
            hmcProfileIoslot.setAdapterId(adapterId);
            hmcProfileIoslot.setIsRequired(Boolean.parseBoolean(newProfileIOSlot.getIsRequired()));
            hmcProfileIoslot.setProfileId(profileId);

            if (hmcProfileIoslot.getId() == null) {
                hmcProfileIoslotRepository.save(hmcProfileIoslot);
            } else {
                hmcProfileIoslotRepository.updateEntity(hmcProfileIoslot);
            }
            oldProfileIOSlotMap.remove(adapterId);
        }
        for (HmcProfileIoslot oldProfileIOSlotToDelete : oldProfileIOSlotMap.values()) {
            hmcProfileIoslotRepository.delete(oldProfileIOSlotToDelete);
        }
    }

    private void syncAdapter(Long profileId, List<ProfileVirtualIOAdapterSubclass> subclasses) throws Exception {
        if (null != subclasses) {
            List<HmcProfileNetworkAdapter> hmcProfileNetworkAdapters = hmcProfileNetworkAdapterRepository.queryByProfileId(profileId);
            Map<Integer, HmcProfileNetworkAdapter> hmcProfileNetworkAdapterMap = new HashMap<>();
            for (HmcProfileNetworkAdapter hmcProfileNetworkAdapter : hmcProfileNetworkAdapters) {
                hmcProfileNetworkAdapterMap.put(hmcProfileNetworkAdapter.getAdapterId(), hmcProfileNetworkAdapter);
            }
            List<HmcProfileFibreAdapter> hmcProfileFibreAdapters = hmcProfileFibreAdapterRepository.queryByProfileId(profileId);
            Map<Integer, HmcProfileFibreAdapter> hmcProfileFibreAdapterMap = new HashMap<>();
            for (HmcProfileFibreAdapter hmcProfileFibreAdapter : hmcProfileFibreAdapters) {
                hmcProfileFibreAdapterMap.put(hmcProfileFibreAdapter.getAdapterId(), hmcProfileFibreAdapter);
            }
            List<HmcProfileScsiAdapter> hmcProfileScsiAdapters = hmcProfileScsiAdapterRepository.queryByProfileId(profileId);
            Map<Integer, HmcProfileScsiAdapter> hmcProfileScsiAdapterMap = new HashMap<>();
            for (HmcProfileScsiAdapter hmcProfileScsiAdapter : hmcProfileScsiAdapters) {
                hmcProfileScsiAdapterMap.put(hmcProfileScsiAdapter.getAdapterId(), hmcProfileScsiAdapter);
            }
            for (ProfileVirtualIOAdapterSubclass adapter : subclasses) {
                // 以太网
                if (adapter.getProfileClientNetworkAdapter() != null) {
                    insertOrUpdateNetworkAdapter(profileId, adapter.getProfileClientNetworkAdapter());
                    hmcProfileNetworkAdapterMap.remove(stringToInt(adapter.getProfileClientNetworkAdapter().getVirtualSlotNumber()));
                }
                if (adapter.getProfileTrunkAdapter() != null) {
                    insertOrUpdateNetworkAdapter(profileId, adapter.getProfileTrunkAdapter());
                    hmcProfileNetworkAdapterMap.remove(stringToInt(adapter.getProfileTrunkAdapter().getVirtualSlotNumber()));
                }
                // 光迁通道
                if (adapter.getProfileVirtualFibreChannelClientAdapter() != null) {
                    insertOrUpdateFibreAdapter(profileId, adapter.getProfileVirtualFibreChannelClientAdapter());
                    hmcProfileFibreAdapterMap.remove(stringToInt(adapter.getProfileVirtualFibreChannelClientAdapter().getVirtualSlotNumber()));
                }
                if (adapter.getProfileVirtualFibreChannelServerAdapter() != null) {
                    insertOrUpdateFibreAdapter(profileId, adapter.getProfileVirtualFibreChannelServerAdapter());
                    hmcProfileFibreAdapterMap.remove(stringToInt(adapter.getProfileVirtualFibreChannelServerAdapter().getVirtualSlotNumber()));
                }
                // SCSI
                if (adapter.getProfileVirtualSCSIClientAdapter() != null) {
                    insertOrUpdateScsiAdapter(profileId, adapter.getProfileVirtualSCSIClientAdapter());
                    hmcProfileScsiAdapterMap.remove(stringToInt(adapter.getProfileVirtualSCSIClientAdapter().getVirtualSlotNumber()));
                }
                if (adapter.getProfileVirtualSCSIServerAdapter() != null) {
                    insertOrUpdateScsiAdapter(profileId, adapter.getProfileVirtualSCSIServerAdapter());
                    hmcProfileScsiAdapterMap.remove(stringToInt(adapter.getProfileVirtualSCSIServerAdapter().getVirtualSlotNumber()));
                }
            }
            for (HmcProfileNetworkAdapter adapter : hmcProfileNetworkAdapterMap.values()) {
                hmcProfileNetworkAdapterRepository.delete(adapter);
            }
            for (HmcProfileFibreAdapter adapter : hmcProfileFibreAdapterMap.values()) {
                hmcProfileFibreAdapterRepository.delete(adapter);
            }
            for (HmcProfileScsiAdapter adapter : hmcProfileScsiAdapterMap.values()) {
                hmcProfileScsiAdapterRepository.delete(adapter);
            }
        } else {
            // 2019-08-20 : 如果将概要文件中的所有适配器都删除并执行保存,subclasses会是null,所以这里也要同步删除\
            hmcProfileNetworkAdapterRepository.deleteByProfileId(profileId);
            hmcProfileFibreAdapterRepository.deleteByProfileId(profileId);
            hmcProfileScsiAdapterRepository.deleteByProfileId(profileId);
        }
    }

    private void insertOrUpdateNetworkAdapter(Long profileId, ProfileClientNetworkAdapter adapter) throws Exception {
        if (null == adapter) {
            return;
        }
        int adapterId = stringToInt(adapter.getVirtualSlotNumber());
        HmcProfileNetworkAdapter adapterOld = hmcProfileNetworkAdapterRepository.queryByProfileIdAndAdapterId(profileId, adapterId);
        HmcProfileNetworkAdapter adapterNew = adapterOld == null ? new HmcProfileNetworkAdapter() : adapterOld;
        adapterNew.setProfileId(profileId);
        adapterNew.setAdapterId(adapterId);
        adapterNew.setVirtualSwitchId(stringToInt(adapter.getVirtualSwitchID()));
        adapterNew.setVirtualSwitchName(adapter.getVirtualSwitchName());
        adapterNew.setVirtualVlanId(stringToInt(adapter.getPortVlanID()));
        adapterNew.setIsRequired(Boolean.parseBoolean(adapter.getIsRequired()));
        adapterNew.setIsTaggedVlanSupported(Boolean.parseBoolean(adapter.getIsTaggedVlanSupported()));
        adapterNew.setTaggedVlanIds(adapter.getTaggedVlanIds());
        adapterNew.setPriority(null);
        if (adapterNew.getId() == null) {
            hmcProfileNetworkAdapterRepository.save(adapterNew);
        } else {
            hmcProfileNetworkAdapterRepository.updateEntity(adapterNew);
        }
    }

    private void insertOrUpdateNetworkAdapter(Long profileId, ProfileTrunkAdapter adapter) throws Exception {
        if (null == adapter) {
            return;
        }
        int adapterId = stringToInt(adapter.getVirtualSlotNumber());
        HmcProfileNetworkAdapter adapterOld = hmcProfileNetworkAdapterRepository.queryByProfileIdAndAdapterId(profileId, adapterId);
        HmcProfileNetworkAdapter adapterNew = adapterOld == null ? new HmcProfileNetworkAdapter() : adapterOld;
        adapterNew.setProfileId(profileId);
        adapterNew.setAdapterId(stringToInt(adapter.getVirtualSlotNumber()));
        adapterNew.setVirtualSwitchId(stringToInt(adapter.getVirtualSwitchID()));
        adapterNew.setVirtualSwitchName(adapter.getVirtualSwitchName());
        adapterNew.setVirtualVlanId(stringToInt(adapter.getPortVlanID()));
        adapterNew.setIsRequired(Boolean.parseBoolean(adapter.getIsRequired()));
        adapterNew.setIsTaggedVlanSupported(Boolean.parseBoolean(adapter.getIsTaggedVlanSupported()));
        adapterNew.setTaggedVlanIds(adapter.getTaggedVlanIds());
        adapterNew.setPriority(stringToInt(adapter.getTrunkPriority()));
        if (adapterNew.getId() == null) {
            hmcProfileNetworkAdapterRepository.save(adapterNew);
        } else {
            hmcProfileNetworkAdapterRepository.updateEntity(adapterNew);
        }
    }

    private void insertOrUpdateFibreAdapter(Long profileId, ProfileVirtualFibreChannelClientAdapter adapter) throws Exception {
        if (null == adapter) {
            return;
        }
        int adapterId = stringToInt(adapter.getVirtualSlotNumber());
        HmcProfileFibreAdapter adapterOld = hmcProfileFibreAdapterRepository.queryByProfileIdAndAdapterId(profileId, adapterId);
        HmcProfileFibreAdapter adapterNew = adapterOld == null ? new HmcProfileFibreAdapter() : adapterOld;
        adapterNew.setProfileId(profileId);
        adapterNew.setAdapterId(stringToInt(adapter.getVirtualSlotNumber()));
        adapterNew.setConnectingPartitionId(stringToInt(adapter.getConnectingPartitionID()));
        adapterNew.setConnectingVirtualSlotNumber(stringToInt(adapter.getConnectingVirtualSlotNumber()));
        adapterNew.setIsRequired(Boolean.parseBoolean(adapter.getIsRequired()));
        adapterNew.setType(adapter.getAdapterType());
        adapterNew.setWwpns(adapter.getWwpns());
        if (adapterNew.getId() == null) {
            hmcProfileFibreAdapterRepository.save(adapterNew);
        } else {
            hmcProfileFibreAdapterRepository.updateEntity(adapterNew);
        }
    }

    private void insertOrUpdateFibreAdapter(Long profileId, ProfileVirtualFibreChannelServerAdapter adapter) throws Exception {
        if (null == adapter) {
            return;
        }
        int adapterId = stringToInt(adapter.getVirtualSlotNumber());
        HmcProfileFibreAdapter adapterOld = hmcProfileFibreAdapterRepository.queryByProfileIdAndAdapterId(profileId, adapterId);
        HmcProfileFibreAdapter adapterNew = adapterOld == null ? new HmcProfileFibreAdapter() : adapterOld;
        adapterNew.setProfileId(profileId);
        adapterNew.setAdapterId(stringToInt(adapter.getVirtualSlotNumber()));
        adapterNew.setConnectingPartitionId(stringToInt(adapter.getConnectingPartitionID()));
        adapterNew.setConnectingVirtualSlotNumber(stringToInt(adapter.getConnectingVirtualSlotNumber()));
        adapterNew.setIsRequired(Boolean.parseBoolean(adapter.getIsRequired()));
        adapterNew.setType(adapter.getAdapterType());
        if (adapterNew.getId() == null) {
            hmcProfileFibreAdapterRepository.save(adapterNew);
        } else {
            hmcProfileFibreAdapterRepository.updateEntity(adapterNew);
        }
    }

    private void insertOrUpdateScsiAdapter(Long profileId, ProfileVirtualSCSIClientAdapter adapter) throws Exception {
        if (null == adapter) {
            return;
        }
        int adapterId = stringToInt(adapter.getVirtualSlotNumber());
        HmcProfileScsiAdapter adapterOld = hmcProfileScsiAdapterRepository.queryByProfileIdAndAdapterId(profileId, adapterId);
        HmcProfileScsiAdapter adapterNew = adapterOld == null ? new HmcProfileScsiAdapter() : adapterOld;
        adapterNew.setProfileId(profileId);
        adapterNew.setRemotePartitionId(stringToInt(adapter.getRemotePartitionID()));
        adapterNew.setRemoteSlotNumber(stringToInt(adapter.getRemoteSlotNumber()));
        adapterNew.setType(adapter.getAdapterType());
        adapterNew.setIsRequired(Boolean.parseBoolean(adapter.getIsRequired()));
        adapterNew.setAdapterId(stringToInt(adapter.getVirtualSlotNumber()));
        if (adapterNew.getId() == null) {
            hmcProfileScsiAdapterRepository.save(adapterNew);
        } else {
            hmcProfileScsiAdapterRepository.updateEntity(adapterNew);
        }
    }

    private void insertOrUpdateScsiAdapter(Long profileId, ProfileVirtualSCSIServerAdapter adapter) throws Exception {
        if (null == adapter) {
            return;
        }
        int adapterId = stringToInt(adapter.getVirtualSlotNumber());
        HmcProfileScsiAdapter adapterOld = hmcProfileScsiAdapterRepository.queryByProfileIdAndAdapterId(profileId, adapterId);
        HmcProfileScsiAdapter adapterNew = adapterOld == null ? new HmcProfileScsiAdapter() : adapterOld;
        adapterNew.setProfileId(profileId);
        adapterNew.setRemotePartitionId(stringToInt(adapter.getRemotePartitionID()));
        adapterNew.setRemoteSlotNumber(stringToInt(adapter.getRemoteSlotNumber()));
        adapterNew.setType(adapter.getAdapterType());
        adapterNew.setIsRequired(Boolean.parseBoolean(adapter.getIsRequired()));
        adapterNew.setAdapterId(stringToInt(adapter.getVirtualSlotNumber()));
        if (adapterNew.getId() == null) {
            hmcProfileScsiAdapterRepository.save(adapterNew);
        } else {
            hmcProfileScsiAdapterRepository.updateEntity(adapterNew);
        }
    }

    @Transactional
    public void updateLparProfile(HmcProfile profile, LogicalPartitionProfileEntry entry, Boolean isActiveProfile,
                                  Long userId) {
        try {
            convertToHmcLparProfile(profile, entry);
            if (null != userId) {
                profile.setMenderId(userId);
                profile.setGmtModify(new Date());
            }
            // 设置是否是分区默认的概要文件
            if (null != isActiveProfile) {
                profile.setIsActiveProfile(isActiveProfile);
            }
            hmcProfileRepository.update(profile);


            LogicalPartitionProfile sdkProfile = entry.getContent().getLogicalPartitionProfile();
            if (null != sdkProfile) {
                // 更新概要文件下IOConfiguration下的设置
                syncIOConfiguration(profile.getId(), sdkProfile.getIoConfigurationInstance());
                // 更新概要文件下的lhea信息
                if (sdkProfile.getHostEthernetAdapterLogicalPorts() != null) {
                    syncProfileHeaLogicalPorts(profile.getId(), sdkProfile.getHostEthernetAdapterLogicalPorts().getHostEthernetAdapterLogicalPortList());
                }
            }


        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Update hmc_lpar_profile table failure. Error message:" + e.getMessage(), e);
        }
    }

    @Transactional
    public void updateVirtualSwitch(HmcVirtualSwitch virtualSwitch, VirtualSwitchEntry entry, Long userId) {
        try {
            if (null != userId) {
                virtualSwitch.setMenderId(userId);
                virtualSwitch.setGmtModify(new Date());
            }

            VirtualSwitch vswitch = entry.getContent().getVirtualSwitch();
            if (null != vswitch) {
                virtualSwitch.setName(vswitch.getSwitchName());
                virtualSwitch.setSwitchId(stringToInt(vswitch.getSwitchId()));
                virtualSwitch.setUuid(entry.getId());
            }

            hmcVirtualSwitchRepository.update(virtualSwitch);
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Update hmc_virtual_switch table failure. Error message:" + e.getMessage(), e);
        }
    }

    private void convertToHmcLparProfile(HmcProfile convertProfile, LogicalPartitionProfileEntry entry) {
        try {
            LogicalPartitionProfile profile = entry.getContent().getLogicalPartitionProfile();
            convertProfile.setUuid(entry.getId());
            convertProfile.setName(profile.getProfileName());
            convertProfile.setType(profile.getProfileType());

            // 如果用户选择了使用所有的资源，则它其它的部分将不再允许用户手动设置
            Boolean value = Boolean.parseBoolean(profile.getAssignAllResources());
            convertProfile.setAssignAllResources(value);
            if (!value) {
                // 处理器设置
                if (null != profile.getProcessorAttributes().getSharedProcessorConfiguration()) {
                    SharedProcessorConfiguration proConfig = profile.getProcessorAttributes().getSharedProcessorConfiguration();
                    convertProfile.setSharedProcessor(true);
                    convertProfile.setMinProUnits(stringToDouble(proConfig.getMinimumProcessingUnits()));
                    convertProfile.setDesProUnits(stringToDouble(proConfig.getDesiredProcessingUnits()));
                    convertProfile.setMaxProUnits(stringToDouble(proConfig.getMaximumProcessingUnits()));
                    convertProfile.setMinProVirt(stringToInt(proConfig.getMinimumVirtualProcessors()));
                    convertProfile.setDesProVirt(stringToInt(proConfig.getDesiredVirtualProcessors()));
                    convertProfile.setMaxProVirt(stringToInt(proConfig.getMaximumVirtualProcessors()));
                    convertProfile.setUncappedWeight(stringToInt(proConfig.getUncappedWeight()));
                    // 根据hmc返回的共享存储池id查询数据库的共享存储池id
                    HmcSystemSharedProcessorPool sharedProcessorPool = sharedProcessorPoolRepository.getByHmcPoolId(Long.valueOf(proConfig.getSharedProcessorPoolID()), convertProfile.getServerId());
                    convertProfile.setSharedProPoolId(sharedProcessorPool.getId());
                } else {
                    convertProfile.setSharedProcessor(false);
                    DedicatedProcessorConfiguration proConfig = profile.getProcessorAttributes().getDedicatedProcessorConfiguration();
                    convertProfile.setMinPro(stringToInt(proConfig.getMinimumProcessors()));
                    convertProfile.setDesPro(stringToInt(proConfig.getDesiredProcessors()));
                    convertProfile.setMaxPro(stringToInt(proConfig.getMaximumProcessors()));
                }
                convertProfile.setProSharingMode(profile.getProcessorAttributes().getSharingMode());
                convertProfile.setDedicatedPro(Boolean.parseBoolean(profile.getProcessorAttributes().getHasDedicatedProcessors()));

                // 内存设置
                convertProfile.setMaxMemory(stringToInt(profile.getProfileMemory().getMaximumMemory()));
                convertProfile.setMinMemory(stringToInt(profile.getProfileMemory().getMinimumMemory()));
                convertProfile.setDesMemory(stringToInt(profile.getProfileMemory().getDesiredMemory()));
                convertProfile.setMemoryBsrCount(stringToInt(profile.getProfileMemory().getBarrierSynchronizationRegisterArrayCount()));
                convertProfile.setMemoryPageRatio(stringToInt(profile.getProfileMemory().getHardwarePageTableRatio()));
                convertProfile.setMemoryMinPageCount(stringToInt(profile.getProfileMemory().getMinimumHugePageCount()));
                convertProfile.setMemoryDesPageCount(stringToInt(profile.getProfileMemory().getDesiredHugePageCount()));
                convertProfile.setMemoryMaxPageCount(stringToInt(profile.getProfileMemory().getMaximumHugePageCount()));

                // 其它设置
                convertProfile.setMaxVirtualIoslots(stringToInt(profile.getIoConfigurationInstance().getMaximumVirtualIoSlots()));
            }
            // 2019-08-06 : 如果概要文件选择了“使用系统中所有资源”，下面这5个属性值也是有的，所以要从上面的if判断中挪出来
            convertProfile.setAutoStart(Boolean.parseBoolean(profile.getAutoStart()));
            convertProfile.setBootMode(profile.getBootMode());
            convertProfile.setConnMonitor(Boolean.parseBoolean(profile.getConnectionMonitoringEnabled()));
            convertProfile.setProcessorCompatibilityMode(profile.getDesiredProcessorCompatibilityMode());
            convertProfile.setRedundantErrorPathReport(Boolean.parseBoolean(profile.getRedundantErrorPathReportingEnabled()));
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Update hmc_profile table failure. Error message:" + e.getMessage(), e);
        }

    }

    public void setPartitionProcessor(HmcPartition partition, PartitionProcessorConfiguration configuration, Long userId) {
        try {
            HmcPartitionProcessor processor = partitionProcessorRepository.getByPartitionId(partition.getId());
            if (processor == null) {
                processor = new HmcPartitionProcessor();
            }
            String sharingMode = configuration.getCurrentSharingMode();
            processor.setSharingMode(sharingMode);
            if ("capped".equals(sharingMode) || "uncapped".equals(sharingMode)) {
                processor.setMinUnits(
                    configuration.getCurrentSharedProcessorConfiguration().getCurrentMinimumProcessingUnits());
                processor.setMaxUnits(
                    configuration.getCurrentSharedProcessorConfiguration().getCurrentMaximumProcessingUnits());
                processor.setCurrUnits(configuration.getCurrentSharedProcessorConfiguration().getCurrentProcessingUnits());
                processor.setPoolId(
                    configuration.getCurrentSharedProcessorConfiguration().getCurrentSharedProcessorPoolID());
                HmcSystemSharedProcessorPool sharedProcessorPool = sharedProcessorPoolRepository.getByHmcPoolId(Long.valueOf(configuration.getCurrentSharedProcessorConfiguration().getCurrentSharedProcessorPoolID()), partition.getServerId());
                processor.setPoolName(sharedProcessorPool.getName());
                processor.setMinVirtualProcessors(
                    configuration.getCurrentSharedProcessorConfiguration().getCurrentMinimumVirtualProcessors());
                processor.setCurrVirtualProcessors(
                    configuration.getCurrentSharedProcessorConfiguration().getAllocatedVirtualProcessors());
                processor.setMaxVirtualProcessors(
                    configuration.getCurrentSharedProcessorConfiguration().getCurrentMaximumVirtualProcessors());
            } else {
                processor.setMaxProcessors(
                    configuration.getCurrentDedicatedProcessorConfiguration().getCurrentMaximumProcessors());
                processor.setMinProcessors(
                    configuration.getCurrentDedicatedProcessorConfiguration().getCurrentMinimumProcessors());
                processor.setCurrProcessors(
                    configuration.getCurrentDedicatedProcessorConfiguration().getCurrentProcessors());
            }
            if (processor.getId() == null) {
                processor.setPartitionId(partition.getId());
                processor.setName(partition.getName());
                processor.setCreatorId(userId);
                processor.setGmtCreate(new Date());
                partitionProcessorRepository.save(processor);
            } else {
                processor.setMenderId(userId);
                processor.setGmtModify(new Date());
                partitionProcessorRepository.update(processor);
            }
            partition.setHmcPartitionProcessor(processor);
        } catch (Exception e) {
            logger.error("Update partitionProcessor failure. Error message:" + e.getMessage(), e);
        }
    }

    public void setPartitionMemory(HmcPartition partition, PartitionMemoryConfiguration configuration, Boolean isVios, Long userId) {
        try {
            HmcPartitionMemory memory = partitionMemoryRepository.getByPartitionId(partition.getId());
            if (memory == null) {
                memory = new HmcPartitionMemory();
            }
            memory.setMinMemory(configuration.getCurrentMinimumMemory());
            memory.setCurrMemory(configuration.getCurrentMemory());
            memory.setMaxMemory(configuration.getCurrentMaximumMemory());
            memory.setBsrArrays(configuration.getCurrentBarrierSynchronizationRegisterArrays());
            if (!isVios) {
                memory.setMinPageCount(configuration.getCurrentMinimumHugePageCount());
                memory.setCurrPageCount(configuration.getCurrentHugePageCount());
                memory.setMaxPageCount(configuration.getCurrentMaximumHugePageCount());
            }
            partition.setHmcPartitionMemory(memory);
            if (memory.getId() == null) {
                memory.setPartitionId(partition.getId());
                memory.setName(partition.getName());
                memory.setCreatorId(userId);
                memory.setGmtCreate(new Date());
                partitionMemoryRepository.save(memory);
            } else {
                memory.setMenderId(userId);
                memory.setGmtModify(new Date());
                partitionMemoryRepository.update(memory);
            }
        } catch (Exception e) {
            logger.error("Update partitionMemory failure. Error message:" + e.getMessage(), e);
        }
    }

    public void setPartitionIo(HmcPartition partition, PartitionIOConfiguration configuration, Long userId) {
        try {
            List<ProfileIOSlot> profileIOSlots =
                Optional.ofNullable(configuration.getProfileIOSlots().getProfileIOSlot()).orElse(new ArrayList<>());
            List<HmcPartitionIo> ios = new ArrayList<>();
            for (ProfileIOSlot ioslot : profileIOSlots) {
                if (null != ioslot.getAssociatedIOSlot().getRelatedIOAdapter().getIoAdapter()) {
                    IOAdapter ioAdapter = ioslot.getAssociatedIOSlot().getRelatedIOAdapter().getIoAdapter();
                    HmcPartitionIo io = new HmcPartitionIo();
                    io.setSlotName(ioAdapter.getDeviceName());
                    io.setDescription(ioAdapter.getDescription());
                    io.setAdapterId(ioAdapter.getAdapterID());
                    Optional.ofNullable(ioAdapter.getLogicalPartitionAssignmentCapable())
                            .map(LogicalPartitionAssignmentCapable::getValue)
                            .ifPresent(io::setIsRequired);
                    ios.add(io);
                }
                if (null != ioslot.getAssociatedIOSlot().getRelatedIOAdapter().getPhysicalFibreChannelAdapter()) {
                    PhysicalFibreChannelAdapter fcAdapter = ioslot.getAssociatedIOSlot().getRelatedIOAdapter().getPhysicalFibreChannelAdapter();
                    HmcPartitionIo io = new HmcPartitionIo();
                    io.setSlotName(fcAdapter.getDeviceName());
                    io.setDescription(fcAdapter.getDescription());
                    io.setAdapterId(fcAdapter.getAdapterID());
                    io.setIsRequired("true");
                    ios.add(io);
                }
            }
            partition.setHmcPartitionIos(ios);

            partitionIoRepository.deleteByPartitionId(partition.getId());
            for (HmcPartitionIo io : ios) {
                io.setPartitionId(partition.getId());
                io.setName(partition.getName());
                io.setCreatorId(userId);
                io.setGmtCreate(new Date());
                partitionIoRepository.save(io);
            }
        } catch (Exception e) {
            logger.error("Update partitionIO failure. Error message:" + e.getMessage(), e);
        }
    }

    @Transactional
    public boolean savePartition(HmcPartition par, Long userId) {
        try {
            par.preSave(userId, userId, par.getServerId());
            hmcPartitionRepository.save(par);
            Long parId = par.getId();
            // 保存概要文件信息
            if (null != par.getHmcLparProfile()) {
                HmcProfile profile = par.getHmcLparProfile();
                profile.preSave(userId, userId, parId);
                hmcProfileRepository.save(profile);
                Long profileId = profile.getId();
                // save IO information
                if (null != profile.getHmcProfileIoslot() && !profile.getHmcProfileIoslot().isEmpty()) {
                    for (HmcProfileIoslot ioslot : profile.getHmcProfileIoslot()) {
                        ioslot.setProfileId(profileId);
                        hmcProfileIoslotRepository.save(ioslot);
                    }
                }
                // save virtual network adapter information
                if (null != profile.getHmcProfileNetworkAdapters()
                    && !profile.getHmcProfileNetworkAdapters().isEmpty()) {
                    for (HmcProfileNetworkAdapter network : profile.getHmcProfileNetworkAdapters()) {
                        network.setProfileId(profileId);
                        hmcProfileNetworkAdapterRepository.save(network);
                    }
                }
                // save virtual fibre channel adapter information
                if (null != profile.getHmcProfileFibreAdapters() && !profile.getHmcProfileFibreAdapters().isEmpty()) {
                    for (HmcProfileFibreAdapter fibre : profile.getHmcProfileFibreAdapters()) {
                        fibre.setProfileId(profileId);
                        hmcProfileFibreAdapterRepository.save(fibre);
                    }
                }
                // save virtual SCSI adapter information
                if (null != profile.getHmcProfileScsiAdapters() && !profile.getHmcProfileScsiAdapters().isEmpty()) {
                    for (HmcProfileScsiAdapter scsi : profile.getHmcProfileScsiAdapters()) {
                        scsi.setProfileId(profileId);
                        hmcProfileScsiAdapterRepository.save(scsi);
                    }
                }
                // save hea information
                if (null != profile.getHmcProfileLheas() && !profile.getHmcProfileLheas().isEmpty()) {
                    for (HmcProfileLhea hea : profile.getHmcProfileLheas()) {
                        hea.setProfileId(profileId);
                        hmcProfileLheaRepository.save(hea);
                    }
                }
            }
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Save partiton failure. Error message:" + e.getMessage(), e);
            return false;
        }
    }

    @Transactional
    public boolean saveProfile(HmcProfile profile, Long partitionId, Long userId) {
        try {
            profile.preSave(userId, userId, partitionId);
            profile.setStatus("PROFILE_CREATING");
            hmcProfileRepository.save(profile);

            // IO设置
            if (profile.getHmcProfileIoslot() != null) {
                for (HmcProfileIoslot ioslot : profile.getHmcProfileIoslot()) {
                    ioslot.setProfileId(profile.getId());
                    hmcProfileIoslotRepository.save(ioslot);
                }
            }
            // vfc设置
            if (profile.getHmcProfileFibreAdapters() != null) {
                for (HmcProfileFibreAdapter hmcProfileFibreAdapter : profile.getHmcProfileFibreAdapters()) {
                    hmcProfileFibreAdapter.setProfileId(profile.getId());
                    hmcProfileFibreAdapterRepository.save(hmcProfileFibreAdapter);
                }
            }
            // lhea设置
            if (profile.getHmcProfileLheas() != null) {
                for (HmcProfileLhea hmcProfileLhea : profile.getHmcProfileLheas()) {
                    hmcProfileLhea.setProfileId(profile.getId());
                    hmcProfileLheaRepository.save(hmcProfileLhea);
                }
            }
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Save partiton profile failure. Error message:" + e.getMessage(), e);
            return false;
        }
    }

    @Transactional
    public boolean removePartition(Long parId, Long userId) {
        try {
            // 删除概要文件中的ioslot记录
            hmcProfileIoslotRepository.deleteByPartitionId(parId);
            // 删除虚拟以太网适配器记录
            hmcProfileNetworkAdapterRepository.deleteByPartitionId(parId);
            // 删除虚拟光纤通道适配器记录
            hmcProfileFibreAdapterRepository.deleteByPartitionId(parId);
            // 删除虚拟SCSI适配器记录
            hmcProfileScsiAdapterRepository.deleteByPartitionId(parId);
            // 删除概要文件
            hmcProfileRepository.deleteByPartitionId(parId, userId);
            // 删除分区虚拟scsi记录
            hmcPartitionScsiAdapterRepository.deleteByPartitionId(parId);
            // 删除虚拟光纤通道mapping信息
            hmcVirtualFibreChannelMappingRepository.deleteByViosId(parId);
            hmcVirtualFibreChannelMappingRepository.updateByPartitionId(parId);
            hmcPartitionVfcAdapterRepository.deleteByPartitionId(parId);
            // 删除物理光纤通道信息
            hmcPhysicalFibreChannelRepository.deleteByViosId(parId);
            // 删除分区记录
            hmcPartitionRepository.remove(parId, userId);
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Remove partiton failure. Error message:" + e.getMessage(), e);
            return false;
        }
    }

    @Transactional
    public boolean removeProfile(Long profileId, Long userId) {
        try {
            // 删除ioslot记录
            hmcProfileIoslotRepository.deleteByProfileId(profileId);
            // 删除适配器
            hmcProfileFibreAdapterRepository.deleteByProfileId(profileId);
            hmcProfileScsiAdapterRepository.deleteByProfileId(profileId);
            hmcProfileNetworkAdapterRepository.deleteByProfileId(profileId);
            hmcProfileLheaRepository.deleteByProfileId(profileId);
            // 删除概要文件记录
            hmcProfileRepository.remove(profileId, userId);
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Remove partiton profile failure. Error message:" + e.getMessage(), e);
            return false;
        }
    }

    @Transactional
    public boolean removeVirtualStorage(Long viosId) {
        try {
            List<HmcVolumeGroup> volumeGroups = hmcVolumeGroupRepository.query(viosId, null);
            for (HmcVolumeGroup vg : volumeGroups) {
                hmcVirtualDiskRepository.delete(vg.getId(), null);
            }
            hmcVolumeGroupRepository.delete(viosId);
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Remove virtual storage failure. Error message:" + e.getMessage(), e);
            return false;
        }
    }

    @Transactional
    public boolean removePhysicalStorage(Long viosId) {
        try {
            return hmcPhysicalDiskRepository.delete(viosId, null);
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Remove physical storage failure. Error message:" + e.getMessage(), e);
            return false;
        }
    }

    @Transactional
    public Boolean removeServerAttributer(Long serverId) {
        try {
            // 删除服务器io适配器记录
            hmcIoBusRepository.deleteByHmcServerId(serverId);
            hmcIoAdapterRepository.deleteByHmcServerId(serverId);

            // 删除服务器供电记录
            hmcIplConfigRepository.deleteByServerId(serverId);
            // 删除服务器功能设置记录
            hmcSystemCapabilityRepository.deleteByServerId(serverId);
            // 删除服务器内存属性记录
            hmcSystemMemoryConfigRepository.deleteByServerId(serverId);
            // 删除服务器处理器属性记录
            hmcSystemProcessorConfigRepository.deleteByServerId(serverId);

            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Remove HMC server failure. Error message:" + e.getMessage(), e);
            return false;
        }
    }

    @Transactional
    public boolean updatePartition(HmcPartition partition, LogicalPartition logicalPartition,
                                   LogicalPartitionProfileEntry profileEntry, Boolean isDetail, Long userId) {
        try {
            partition.setKeyLockPosition(logicalPartition.getKeylockPosition());
            partition.setProcessorCompatibilityMode(logicalPartition.getCurrentProcessorCompatibilityMode());
            partition.setErrorPathReport(
                Boolean.parseBoolean(logicalPartition.getIsRedundantErrorPathReportingEnabled()));
            // Need to confirm
            partition.setServicePartition(Boolean.parseBoolean(logicalPartition.getIsServicePartition()));
            partition.setName(logicalPartition.getPartitionName());
            partition.setHmcPartitionId(stringToInt(logicalPartition.getPartitionID()));
            partition.setPartitionType(logicalPartition.getPartitionType());
            partition.setCode(logicalPartition.getReferenceCode());
            partition.setOsVersion(logicalPartition.getOperatingSystemVersion());
            partition.setIp(logicalPartition.getResourceMonitoringIPAddress());
            partition.setLedOn(Boolean.parseBoolean(logicalPartition.getIsVirtualServiceAttentionLEDOn()));
            partition.setCurrentProfileSync(logicalPartition.getCurrentProfileSync());
            partition.setMemory(
                stringToDouble(logicalPartition.getPartitionMemoryConfiguration().getCurrentMemory()));
            if (null != logicalPartition.getPartitionProcessorConfiguration()
                .getCurrentSharedProcessorConfiguration()) {
                partition.setProcessor(stringToDouble(logicalPartition.getPartitionProcessorConfiguration()
                    .getCurrentSharedProcessorConfiguration().getCurrentProcessingUnits()));
            } else {
                // 专用的处理器
                partition.setProcessor(stringToDouble(logicalPartition.getPartitionProcessorConfiguration()
                    .getCurrentDedicatedProcessorConfiguration().getCurrentProcessors()));
            }
            partition.setConnMonitorEnabled(Boolean.parseBoolean(logicalPartition.getIsConnectionMonitoringEnabled()));
            partition.setAllowPerformanceCollection(
                Boolean.parseBoolean(logicalPartition.getAllowPerformanceDataCollection()));
            partition.setUuid(logicalPartition.getPartitionUUID());
            partition.setStatus(logicalPartition.getPartitionState());
            partition.setCurrentMaxVirtualIOSlots(stringToInt(logicalPartition.getPartitionIOConfiguration().getCurrentMaximumVirtualIOSlots()));
            partition.setPendingProcessorCompatibilityMode(logicalPartition.getPendingProcessorCompatibilityMode());

            // 是否是用户更新了分区
            if (null != userId) {
                partition.setMenderId(userId);
                partition.setGmtModify(new Date());
            }
            hmcPartitionRepository.update(partition);

            // 同步处理器
            this.setPartitionProcessor(partition, logicalPartition.getPartitionProcessorConfiguration(), userId);

            // 同步内存
            this.setPartitionMemory(partition, logicalPartition.getPartitionMemoryConfiguration(), false, userId);

            // 同步IO
            this.setPartitionIo(partition, logicalPartition.getPartitionIOConfiguration(), userId);

            // 如果获取分区属性，获取属性详情值
            if (isDetail) {
                setPartitionProcessor(partition, logicalPartition.getPartitionProcessorConfiguration(), userId);
                setPartitionMemory(partition, logicalPartition.getPartitionMemoryConfiguration(), false, userId);
                setPartitionIo(partition, logicalPartition.getPartitionIOConfiguration(), userId);
            }

            // 更新分区概要文件
            if (null != profileEntry && null != partition.getHmcLparProfile()) {
                String profileUuid = null;
                Boolean isActiveProfile = false;
                if (null != logicalPartition.getAssociatedPartitionProfile()) {
                    String[] values = logicalPartition.getAssociatedPartitionProfile().getHref().split("/");
                    profileUuid = values[values.length - 1];
                    if (profileUuid.equals(profileEntry.getId())) {
                        isActiveProfile = true;
                    }
                }
                partition.getHmcLparProfile().setServerId(partition.getServerId());
                convertToHmcLparProfile(partition.getHmcLparProfile(), profileEntry);
                partition.getHmcLparProfile().setIsActiveProfile(isActiveProfile);
                if (null != userId) {
                    partition.getHmcLparProfile().setMenderId(userId);
                    partition.getHmcLparProfile().setGmtModify(new Date());
                }
                hmcProfileRepository.update(partition.getHmcLparProfile());
            }
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Fail to update logical parition information. Error message:" + e.getMessage(), e);
            return false;
        }
    }

    @Transactional
    public boolean updatePartition(HmcPartition partition, VirtualIOServer virtualIOServer,
                                   LogicalPartitionProfileEntry profileEntry, Boolean isDetail, Long userId) {
        try {
            partition.setKeyLockPosition(virtualIOServer.getKeylockPosition());
            partition.setProcessorCompatibilityMode(virtualIOServer.getCurrentProcessorCompatibilityMode());
            partition.setErrorPathReport(
                Boolean.parseBoolean(virtualIOServer.getIsRedundantErrorPathReportingEnabled()));
            // Need to confirm
            partition.setServicePartition(Boolean.parseBoolean(virtualIOServer.getIsServicePartition()));
            partition.setName(virtualIOServer.getPartitionName());
            partition.setHmcPartitionId(stringToInt(virtualIOServer.getPartitionID()));
            partition.setPartitionType(virtualIOServer.getPartitionType());
            partition.setCode(virtualIOServer.getReferenceCode());
            partition.setOsVersion(virtualIOServer.getOperatingSystemVersion());
            partition.setIp(virtualIOServer.getResourceMonitoringIPAddress());
            partition.setLedOn(Boolean.parseBoolean(virtualIOServer.getIsVirtualServiceAttentionLEDOn()));
            partition.setCurrentProfileSync(virtualIOServer.getCurrentProfileSync());
            partition.setMemory(
                stringToDouble(virtualIOServer.getPartitionMemoryConfiguration().getCurrentMemory()));
            if (null != virtualIOServer.getPartitionProcessorConfiguration().getCurrentSharedProcessorConfiguration()) {
                partition.setProcessor(stringToDouble(virtualIOServer.getPartitionProcessorConfiguration()
                    .getCurrentSharedProcessorConfiguration().getCurrentProcessingUnits()));
            } else {
                // 专用的处理器
                partition.setProcessor(stringToDouble(virtualIOServer.getPartitionProcessorConfiguration()
                    .getCurrentDedicatedProcessorConfiguration().getCurrentProcessors()));
            }
            partition.setConnMonitorEnabled(Boolean.parseBoolean(virtualIOServer.getIsConnectionMonitoringEnabled()));
            partition.setAllowPerformanceCollection(Boolean.parseBoolean(virtualIOServer.getAllowPerformanceDataCollection()));
            partition.setUuid(virtualIOServer.getPartitionUUID());
            partition.setStatus(virtualIOServer.getPartitionState());
            partition.setCurrentMaxVirtualIOSlots(stringToInt(virtualIOServer.getPartitionIOConfiguration().getCurrentMaximumVirtualIOSlots()));
            partition.setPendingProcessorCompatibilityMode(virtualIOServer.getPendingProcessorCompatibilityMode());


            // 是否是用户更新了分区
            if (null != userId) {
                partition.setMenderId(userId);
                partition.setGmtModify(new Date());
            }

            // 同步处理器
            this.setPartitionProcessor(partition, virtualIOServer.getPartitionProcessorConfiguration(), userId);

            // 同步内存
            this.setPartitionMemory(partition, virtualIOServer.getPartitionMemoryConfiguration(), false, userId);

            // 同步IO
            this.setPartitionIo(partition, virtualIOServer.getPartitionIOConfiguration(), userId);

            hmcPartitionRepository.update(partition);
            // 如果获取分区属性，获取属性详情值
            if (isDetail) {
                setPartitionProcessor(partition, virtualIOServer.getPartitionProcessorConfiguration(), userId);
                setPartitionMemory(partition, virtualIOServer.getPartitionMemoryConfiguration(), true, userId);
                setPartitionIo(partition, virtualIOServer.getPartitionIOConfiguration(), userId);
            }

            // 更新vfc适配器
            hmcPartitionService.updateVirtualFibreChannelMappingForVios(partition, virtualIOServer.getVirtualFibreChannelMappings());

            // 更新分区概要文件
            if (null != profileEntry && null != partition.getHmcLparProfile()) {
                String profileUuid = null;
                Boolean isActiveProfile = false;
                if (null != virtualIOServer.getAssociatedPartitionProfile()) {
                    String[] values = virtualIOServer.getAssociatedPartitionProfile().getHref().split("/");
                    profileUuid = values[values.length - 1];
                    if (profileUuid.equals(profileEntry.getId())) {
                        isActiveProfile = true;
                    }
                }
                partition.getHmcLparProfile().setServerId(partition.getServerId());
                convertToHmcLparProfile(partition.getHmcLparProfile(), profileEntry);
                partition.getHmcLparProfile().setIsActiveProfile(isActiveProfile);
                if (null != userId) {
                    partition.getHmcLparProfile().setMenderId(userId);
                    partition.getHmcLparProfile().setGmtModify(new Date());
                }
                hmcProfileRepository.update(partition.getHmcLparProfile());
            }
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Fail to update VIOS parition information. Error message:" + e.getMessage(), e);
            return false;
        }
    }

    @Transactional
    public Boolean updateHostEthernetAdapter(Long serverId, HostEthernetAdapter hea, String uuid) {
        try {
            // 获取和更新主机以太网信息
            HmcHostEthernetAdapter hmcHea = hmcHostEthernetAdapterRepository.getByAdapterId(serverId,
                Long.parseLong(hea.getAdapterID()));
            if (null == hmcHea) {
                hmcHea = new HmcHostEthernetAdapter();
                hmcHea.setServerId(serverId);
                hmcHea.setAdapterId(Long.parseLong(hea.getAdapterID()));
                hmcHea.setUuid(uuid);
                hmcHea.setName(hea.getPhysicalLocationCode());
                hmcHostEthernetAdapterRepository.save(hmcHea);
            } else {
                hmcHea.setServerId(serverId);
                hmcHea.setAdapterId(Long.parseLong(hea.getAdapterID()));
                hmcHea.setName(hea.getPhysicalLocationCode());
                hmcHea.setUuid(uuid);
                hmcHostEthernetAdapterRepository.updateEntity(hmcHea);
            }

            List<HostEthernetAdapterPortGroup> portGroups = hea.getPortGroups().getHostEthernetAdapterPortGroup();
            if (null != portGroups) {
                hmcHeaPhysicalPortRepository.deleteByHeaId(hmcHea.getId());
                hmcHeaLogicalPortRepository.deleteByHeaId(hmcHea.getId());
                for (HostEthernetAdapterPortGroup portGroup : portGroups) {
                    // 更新主机以太网逻辑和物理端口信息
                    updateHeaPort(hmcHea.getId(), portGroup);
                }
            }
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Fail to update host ethernet adapter information. Error message:" + e.getMessage(), e);
            return false;
        }
    }

    private void updateHeaPort(Long heaId, HostEthernetAdapterPortGroup portGroup) throws Exception {
        // 更新物理端口
        List<HostEthernetAdapterPhysicalPort> physicalPorts = portGroup.getPhysicalPorts()
            .getHostEthernetAdapterPhysicalPort();
        for (HostEthernetAdapterPhysicalPort physicalPort : physicalPorts) {
            HmcHeaPhysicalPort hmcHeaPhysicalPort = new HmcHeaPhysicalPort();
            hmcHeaPhysicalPort.setHeaId(heaId);
            hmcHeaPhysicalPort.setConnectionSpeed(physicalPort.getPendingConnectionSpeed());
            hmcHeaPhysicalPort.setLinkUp(Boolean.parseBoolean(physicalPort.getLinkUp()));
            hmcHeaPhysicalPort.setDuplexMode(physicalPort.getPendingDuplexMode());
            hmcHeaPhysicalPort.setFlowControl(Boolean.parseBoolean(physicalPort.getPendingFlowControlEnabled()));
            hmcHeaPhysicalPort.setTransmitFlowControl(Boolean.parseBoolean(physicalPort.getTransmitFlowControlEnabled()));
            hmcHeaPhysicalPort.setReceiveFlowControl(Boolean.parseBoolean(physicalPort.getReceiveFlowControlEnabled()));
            hmcHeaPhysicalPort.setMaxReceivePacket(physicalPort.getMaximumReceivePacketSize());
            hmcHeaPhysicalPort.setPortLocation(physicalPort.getPhysicalPortLocationCode());
            hmcHeaPhysicalPort.setPortId(stringToInt(physicalPort.getPhysicalPortID()));
            hmcHeaPhysicalPort.setPortType(physicalPort.getPhysicalPortType());
            hmcHeaPhysicalPort.setPortGroupId(stringToInt(portGroup.getPortGroupID()));
            hmcHeaPhysicalPort.setMultiCoreScaling(stringToInt(portGroup.getPendingMultiCoreScaling()));
            hmcHeaPhysicalPort.setSupportedMultiCoreScaling(portGroup.getSupportedMultiCoreScalingValues());
            hmcHeaPhysicalPort.setOwner(physicalPort.getOwner());

            hmcHeaPhysicalPortRepository.save(hmcHeaPhysicalPort);
        }

        // 更新逻辑端口
        List<HostEthernetAdapterLogicalPort> logicalPorts = portGroup.getLogicalPorts()
            .getHostEthernetAdapterLogicalPort();
        for (HostEthernetAdapterLogicalPort logicalPort : logicalPorts) {
            HmcHeaLogicalPort hmcHeaLogicalPort = new HmcHeaLogicalPort();
            hmcHeaLogicalPort.setHeaId(heaId);
            hmcHeaLogicalPort.setAdapterId(Long.parseLong(logicalPort.getAdapterID()));
            hmcHeaLogicalPort.setLogicalPortId(stringToInt(logicalPort.getLogicalPortID()));
            hmcHeaLogicalPort.setName("Logical Port " + logicalPort.getLogicalPortID());
            hmcHeaLogicalPort.setPortState(logicalPort.getPortState());
            hmcHeaLogicalPort.setMacAddress(logicalPort.getmACAddress());
            hmcHeaLogicalPort.setAllowedOSMacAddresses(logicalPort.getAllowedOSMACAddresses());
            hmcHeaLogicalPort.setAllowedVlanIds(logicalPort.getAllowedVLANIDs());
            hmcHeaLogicalPort.setPortGroupId(stringToInt(logicalPort.getPortGroupID()));
            if (logicalPort.getPartitionLink() != null && logicalPort.getPartitionLink().getHref() != null) {
                String partitionHref = logicalPort.getPartitionLink().getHref();
                String partitionUuid = new String(partitionHref.toCharArray(), partitionHref.indexOf("LogicalPartition/") + 17, 36);
                HmcPartition hmcPartition = hmcPartitionRepository.getByUuid(partitionUuid);
                if (hmcPartition != null) {
                    hmcHeaLogicalPort.setPartitionId(hmcPartition.getId());
                }
            }

            hmcHeaLogicalPortRepository.save(hmcHeaLogicalPort);
        }
    }

    @Transactional
    public Boolean deleteHostEthernetAdapter(Long serverId) {
        try {
            // delete HEA of the server
            hmcHeaLogicalPortRepository.deleteByServerId(serverId);
            hmcHeaPhysicalPortRepository.deleteByServerId(serverId);
            hmcHostEthernetAdapterRepository.deleteByServerId(serverId);
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Fail to delete host ethernet adapter information. Error message:" + e.getMessage(), e);
            return false;
        }
    }

    @Transactional
    public Boolean updateLastActivatedProfile(Long partitionId, Long profileId) {
        try {
            HmcProfile oldLastActivatedprofile = hmcProfileRepository.getIsLastActived(partitionId);
            if (null != oldLastActivatedprofile) {
                oldLastActivatedprofile.setIsLastActivated(false);
                hmcProfileRepository.update(oldLastActivatedprofile);
            }

            HmcProfile hmcProfile = hmcProfileRepository.queryById(profileId);
            hmcProfile.setIsLastActivated(true);
            hmcProfile.setLastActivated(new Date());
            hmcProfileRepository.update(hmcProfile);
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Fail to update the last activated profile. Error message:" + e.getMessage(), e);
            return false;
        }
    }

    @Transactional
    public Boolean setActivedProfile(Long partitionId, Long profileId) {
        try {
            HmcProfile oldActivedProfile = hmcProfileRepository.getActiveProfile(partitionId);
            if (null != oldActivedProfile && profileId.equals(oldActivedProfile.getId())) {
                return true;
            }
            if (null != oldActivedProfile) {
                oldActivedProfile.setIsActiveProfile(false);
                hmcProfileRepository.update(oldActivedProfile);
            }

            HmcProfile hmcProfile = hmcProfileRepository.queryById(profileId);
            hmcProfile.setIsActiveProfile(true);
            hmcProfileRepository.update(hmcProfile);
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Fail to update the actived profile. Error message:" + e.getMessage(), e);
            return false;
        }
    }

    @Transactional
    public Boolean setUnactivedProfile(Long partitionId) {
        try {
            HmcProfile activedProfile = hmcProfileRepository.getActiveProfile(partitionId);
            if (activedProfile == null) {
                logger.error("Can't find actived profile for partitionOId: " + partitionId);
                return false;
            }
            activedProfile.setIsActiveProfile(false);
            hmcProfileRepository.update(activedProfile);
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Fail to update the unactived profile. Error message:" + e.getMessage(), e);
            return false;
        }
    }

    @Transactional
    public Boolean removeHmcVendor(Long vendorId, Long userId) {
        try {
            List<HmcServer> hmcServers = hmcServerRepository.listByVendorId(vendorId);
            if (hmcServers == null || hmcServers.size() == 0) {
                return true;
            }
            for (HmcServer server : hmcServers) {
                Long serverId = server.getId();
                // 删除服务器属性数据
                removeServerAttributer(serverId);

                // 删除分区信息
                List<HmcPartition> hmcPartitions = hmcPartitionRepository.listByServerId(serverId);
                if (hmcPartitions != null) {
                    for (HmcPartition par : hmcPartitions) {
                        Long parId = par.getId();
                        if ("Virtual IO Server".equals(par.getPartitionType())) {
                            // 删除虚拟存储信息
                            removeVirtualStorage(par.getId());
                            // 删除物理存储信息
                            removePhysicalStorage(par.getId());
                        }
                        removePartition(parId, userId);
                    }
                }

                // 删除主机以太网
                deleteHostEthernetAdapter(serverId);

                // 删除虚拟交换机
                hmcVirtualSwitchRepository.removeByServerId(serverId, userId);

                hmcServerRepository.remove(serverId, userId);
            }
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Fail to remove HMC vendor " + vendorId + " . Error message:" + e.getMessage(), e);
            return false;
        }
    }

    @Transactional
    public void syncPhysicalFibreChannel(HmcPartition vios, List<ProfileIOSlot> profileIoSlots) {
        try {
            // 获取vios原始的光纤通道信息
            List<HmcPhysicalFibreChannel> fibreChannels = hmcPhysicalFibreChannelRepository.listByPartitionId(vios.getId());
            Map<String, HmcPhysicalFibreChannel> oldFcMap = Maps.newHashMap();
            for (HmcPhysicalFibreChannel fc : fibreChannels) {
                oldFcMap.put(fc.getUniqueDeviceId(), fc);
            }

            // 如果这个vois没有配置物理光纤通道，之前它的光纤通道信息全部删除
            if (null == profileIoSlots || profileIoSlots.isEmpty()) {
                Iterator<HmcPhysicalFibreChannel> iteratorFc = oldFcMap.values().iterator();
                while (iteratorFc.hasNext()) {
                    hmcPhysicalFibreChannelRepository.delete(iteratorFc.next());
                }
                return;
            }

            // 更新或插入新的光纤通道信息
            for (ProfileIOSlot ioSlot : profileIoSlots) {
                RelatedIOAdapter relatedIOAdapter = ioSlot.getAssociatedIOSlot().getRelatedIOAdapter();
                if (null != relatedIOAdapter) {
                    PhysicalFibreChannelAdapter fcAdapter = relatedIOAdapter.getPhysicalFibreChannelAdapter();
                    if (null != fcAdapter && null != fcAdapter.getPhysicalFibreChannelPorts()) {
                        List<PhysicalFibreChannelPort> ports = fcAdapter.getPhysicalFibreChannelPorts()
                            .getPhysicalFibreChannelPort();
                        for (PhysicalFibreChannelPort port : ports) {
                            if (oldFcMap.containsKey(port.getUniqueDeviceID())) {
                                HmcPhysicalFibreChannel fibreChannel = oldFcMap.get(port.getUniqueDeviceID());
                                fibreChannel.setDescription(fcAdapter.getDescription());
                                fibreChannel.setName(port.getPortName());
                                fibreChannel.setLocationCode(port.getLocationCode());
                                fibreChannel.setWwpn(port.getWwpn());
                                fibreChannel.setWwnn(port.getWwnn());
                                fibreChannel.setAvailablePorts(stringToInt(port.getAvailablePorts()));
                                hmcPhysicalFibreChannelRepository.updateEntity(fibreChannel);
                                oldFcMap.remove(port.getUniqueDeviceID());
                            } else {
                                HmcPhysicalFibreChannel fibreChannel = new HmcPhysicalFibreChannel();
                                fibreChannel.setPartitionId(vios.getId());
                                fibreChannel.setDescription(fcAdapter.getDescription());
                                fibreChannel.setName(port.getPortName());
                                fibreChannel.setLocationCode(port.getLocationCode());
                                fibreChannel.setUniqueDeviceId(port.getUniqueDeviceID());
                                fibreChannel.setWwpn(port.getWwpn());
                                fibreChannel.setWwnn(port.getWwnn());
                                fibreChannel.setAvailablePorts(stringToInt(port.getAvailablePorts()));
                                hmcPhysicalFibreChannelRepository.save(fibreChannel);
                            }
                        }

                    }
                }
            }

            // 删除在HMC上已经不存在的物理光纤通道
            Iterator<HmcPhysicalFibreChannel> iteratorFc = oldFcMap.values().iterator();
            while (iteratorFc.hasNext()) {
                hmcPhysicalFibreChannelRepository.delete(iteratorFc.next());
            }
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("Update hmc_physical_fibre_channel table failure. Error message:" + e.getMessage(), e);
        }
    }

    // 根据服务器属性值，更新服务器对象
    public void updateHmcServerEntity(HmcServer server, ManagedSystemEntry entry) {
        ManagedSystemContent content = entry.getContent();
        if (content == null) {
            return;
        }

        ManagedSystem system = content.getManagedSystem();
        if (system == null) {
            return;
        }

        server.setUuid(entry.getId());
        server.setName(system.getSystemName());
        server.setStatus(system.getState());
        Optional.of(system).map(ManagedSystem::getMergedReferenceCode).map(MergedReferenceCode::getValue).ifPresent(server::setReferenceCode);
        Optional.of(system).map(ManagedSystem::getSystemFirmware).map(SystemFirmware::getValue).ifPresent(server::setSystemFirmware);
        server.setActivatedLevel(system.getActivatedLevel());
        MachineTypeModelAndSerialNumber tms = system.getMachineTypeModelAndSerialNumber();
        if (tms != null) {
            server.setMachineType(tms.getMachineType());
            server.setModel(tms.getModel());
            server.setSerialNumber(tms.getSerialNumber());
        }
        server.setMaximumPartitions(stringToInt(system.getMaximumPartitions()));
        server.setPhysicalSystemAttentionLedState(system.getPhysicalSystemAttentionLEDState());
        server.setPrimaryIpAddress(system.getPrimaryIPAddress());
        Optional.ofNullable(system.getHostname()).map(Hostname::getValue).ifPresent(server::setHostname);
        server.setServiceProcessorVersion(system.getServiceProcessorVersion());
        server.setManufacturingDefaultConfigurationEnabled(system.getManufacturingDefaultConfigurationEnabled());
    }

    /**
     * 查询iscsi适配器分配的物理盘、虚拟盘、虚拟CD等
     * @param viosId 要查询的vios
     * @return Map.key:插槽号 Map.value:物理盘、虚拟盘、虚拟CD等
     */
    public Map<Long, List<SimpleBean>> getIscsiAssignedByVios(Long viosId) {
        List<SimpleBean> assigns = new ArrayList<>();
        assigns.addAll(hmcPhysicalDiskRepository.query(viosId, null).stream()
                .filter(pv -> Objects.nonNull(pv.getViosSlotId()))
                .map(pv -> new SimpleBean(new Long(pv.getViosSlotId()), pv.getVolumeName(), "物理卷"))
                .collect(Collectors.toList())
        );
        assigns.addAll(hmcVirtualDiskRepository.queryByViosId(viosId).stream()
                .filter(lv -> Objects.nonNull(lv.getViosSlotId()))
                .map(lv -> new SimpleBean(new Long(lv.getViosSlotId()), lv.getDiskName(), "虚拟盘"))
                .collect(Collectors.toList())
        );
        assigns.addAll(hmcVirtualCdRepository.queryByViosSlot(viosId, null).stream()
                .filter(cd -> Objects.nonNull(cd.getViosSlot()))
                .map(cd -> new SimpleBean(new Long(cd.getViosSlot()), cd.getCdName(), "虚拟光学设备"))
                .collect(Collectors.toList())
        );
        return assigns.stream().collect(Collectors.groupingBy(SimpleBean::getId));
    }

    public String checkIscsiMultiAssign(Long viosId) {
        Map<Long, List<SimpleBean>> iscsiAssigns = getIscsiAssignedByVios(viosId);
        StringBuilder message = new StringBuilder();
        iscsiAssigns.entrySet().stream().filter(entry -> entry.getValue().size() > 1).findFirst().ifPresent(entry -> {
            message.append("该VIOS存在SCSI适配器[").append(entry.getKey()).append("]被分配了多个设备：");
            String names = entry.getValue().stream().map(SimpleBean::getName).collect(Collectors.joining("、"));
            message.append(names).append("，暂不支持此种情况下执行当前操作，请调整后再试");
        });
        return message.toString();
    }

    private Integer stringToInt(String var) {
        return var == null ? 0 : Integer.parseInt(var);
    }

    private Double stringToDouble(String var) {
        return var == null ? 0 : Double.parseDouble(var);
    }
}
