美文网首页Ovirt程序员
【Ovirt 笔记】虚拟机相关业务验证分析与整理(2)

【Ovirt 笔记】虚拟机相关业务验证分析与整理(2)

作者: 58bc06151329 | 来源:发表于2018-11-07 15:16 被阅读1次

文前说明

作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。

分析整理的版本为 Ovirt 4.2.3 版本。

11 创建快照

  • 创建快照使用了 CreateSnapshotCommand 类。
  • 验证实现为 validate 方法。
protected boolean validate() {
        return true;
}

12 删除快照

  • 删除快照使用了 RemoveSnapshotCommand 类。
  • 验证实现为 validate 方法。

12.1 虚拟机为空验证

  • 为空返回错误信息 ACTION_TYPE_FAILED_VM_NOT_FOUND
if (vm == null) {
      return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_NOT_FOUND);
}

12.2 Host 虚拟机和外部虚拟机验证

if (!canRunActionOnNonManagedVm()) {
      return false;
}

12.3 数据中心验证

  • 所在数据中心必须存在且状态为启动。
new StoragePoolValidator(getStoragePool()).existsAndUp()

12.4 镜像相关验证

  • 正在执行快照相关操作验证。
public ValidationResult vmSnapshotDisksNotDuringMerge(Guid vmId, Guid mergedSnapshotId) {
        Set<Guid> mergedSnapshotDisksIds = getSnapshotDiskIds(mergedSnapshotId).collect(Collectors.toSet());
        boolean isVmDuringSnapshot =
                !mergedSnapshotDisksIds.isEmpty() &&
                getAllVmLockedSnapshotIds(vmId).flatMap(this::getSnapshotDiskIds).anyMatch(mergedSnapshotDisksIds::contains);

        return isVmDuringSnapshot ? new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_VM_IS_DURING_SNAPSHOT) :
                ValidationResult.VALID;
}
  • 正在预览快照验证。
public ValidationResult vmNotInPreview(Guid vmId) {
        return vmNotInStatus(vmId, SnapshotStatus.IN_PREVIEW, EngineMessage.ACTION_TYPE_FAILED_VM_IN_PREVIEW);
}
  • 快照是否存在验证。
private ValidationResult createSnapshotExistsResult(boolean snapshotExists) {
        return snapshotExists
                ? ValidationResult.VALID
                : new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_VM_SNAPSHOT_DOES_NOT_EXIST);
}
  • 快照类型验证。
    • 只能操作一般规则类型快照。(REGULAR)
快照类型 说明
REGULAR 一般规则的
ACTIVE 激活正在使用的
STATELESS 无状态的
PREVIEW 预览的
NEXT_RUN 接下来运行的
public ValidationResult isRegularSnapshot(Snapshot snapshot) {
        if (SnapshotType.REGULAR != snapshot.getType()) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_VM_SNAPSHOT_TYPE_NOT_REGULAR);
        }
        return ValidationResult.VALID;
}
  • 虚拟机的磁盘快照附加到了其他虚拟机验证。
public ValidationResult vmNotHavingDeviceSnapshotsAttachedToOtherVms(boolean onlyPlugged) {
        List<Disk> vmDisks = getDbFacade().getDiskDao().getAllForVm(vm.getId());
        ValidationResult result =
                new DiskImagesValidator(DisksFilter.filterImageDisks(vmDisks, ONLY_NOT_SHAREABLE, ONLY_ACTIVE))
                        .diskImagesSnapshotsNotAttachedToOtherVms(onlyPlugged);
        if (result != ValidationResult.VALID) {
            return result;
        }
        return ValidationResult.VALID;
}

12.5 虚拟机状态验证

  • 虚拟机必须处于 Down、Up 或 Paused 状态。
public ValidationResult vmQualifiedForSnapshotMerge() {
        if (!vm.isQualifiedForSnapshotMerge()) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_VM_IS_NOT_DOWN_OR_UP,
                    String.format("$VmName %s", vm.getName()));
        }
        return ValidationResult.VALID;
}

12.6 镜像验证

  • 镜像锁定验证。
private boolean validateImagesNotLocked(DiskImagesValidator diskImagesValidator) {
        return !getParameters().isNeedsLocking() || validate(diskImagesValidator.diskImagesNotLocked());
}
  • 镜像状态验证。
getVm().isQualifiedForLiveSnapshotMerge()
  • 磁盘非法验证。
public ValidationResult diskImagesNotIllegal() {
        return diskImagesNotInStatus(ImageStatus.ILLEGAL, EngineMessage.ACTION_TYPE_FAILED_DISKS_ILLEGAL);
}
  • 磁盘拔出验证。
private boolean validateSnapshotDisksArePlugged() {
        Map<Guid, Disk> vmDisks = diskDao.getAllForVm(getVmId())
                .stream()
                .collect(Collectors.toMap(Disk::getId, Function.identity()));

        // If there is an unattached disk, it will not be included in vmDisks, hence it is
        // retrieved by the diskDao. This is less likely to happen as it is not possible
        // to unattach disks with snapshots.
        String unpluggedDisks = getSourceImages()
                .stream()
                .map(DiskImage::getId)
                .map(vmDiskId -> vmDisks.getOrDefault(vmDiskId, diskDao.get(vmDiskId)))
                .filter(disk -> !disk.getPlugged())
                .map(Disk::getDiskAlias)
                .collect(Collectors.joining(System.lineSeparator()));

        if (!unpluggedDisks.isEmpty()) {
            return validate(new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_VM_SNAPSHOT_HAS_UNPLUGGED_OR_UNATTACHED_DISKS,
                    String.format("$diskAliases %s", unpluggedDisks)));
        }
        return true;
}

12.7 模板快照验证

  • 不允许删除模板快照。
if (!validateImageNotInTemplate()) {
                return failValidation(EngineMessage.ACTION_TYPE_FAILED_CANNOT_REMOVE_IMAGE_TEMPLATE);
}

12.8 存储域验证

  • 至少存在一个激活的存储域。
storageDomainsValidator.allDomainsExistAndActive()
  • 存储域中可用的磁盘空间过低。
public ValidationResult allDomainsWithinThresholds() {
        return validOrFirstFailure(entry -> getStorageDomainValidator(entry).isDomainWithinThresholds());
}
......
public ValidationResult hasSpaceForMerge(List<SubchainInfo> subchains, ActionType snapshotActionType) {
        if (storageDomain.getStorageType().isCinderDomain()) {
            return ValidationResult.VALID;
        }
        Long availableSize = storageDomain.getAvailableDiskSizeInBytes();
        double totalSizeForDisks = getTotalSizeForMerge(subchains, snapshotActionType);

        return validateRequiredSpace(availableSize, totalSizeForDisks);
}

13 恢复快照

  • 恢复快照使用了 RestoreAllSnapshotsCommand 类。
  • 验证实现为 validate 方法。

13.1 虚拟机为空验证

  • 为空返回错误信息 ACTION_TYPE_FAILED_VM_NOT_FOUND
if (vm == null) {
      return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_NOT_FOUND);
}

13.2 Host 虚拟机和外部虚拟机验证

if (!canRunActionOnNonManagedVm()) {
      return false;
}

13.3 数据中心验证

  • 所在数据中心必须存在且状态为启动。
new StoragePoolValidator(getStoragePool()).existsAndUp()

13.4 快照相关验证

  • 快照是否存在验证。
snapshotsValidator.snapshotExists(getSnapshot())
  • 虚拟机中该快照是否存在验证。
snapshotsValidator.snapshotExists(getVmId(), getSnapshot().getId())
  • 快照 ID 是否存在验证。
if (Guid.Empty.equals(getSnapshot().getId())) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_CORRUPTED_VM_SNAPSHOT_ID);
}
  • 快照状态验证。
    • 快照没有处于预览状态。
if (getSnapshot().getType() == SnapshotType.REGULAR
                && getSnapshot().getStatus() != SnapshotStatus.IN_PREVIEW) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_SNAPSHOT_NOT_IN_PREVIEW);
}

13.5 存储域验证

  • 至少存在一个激活的存储域。
storageDomainsValidator.allDomainsExistAndActive()

13.6 镜像锁验证

protected boolean performImagesChecks() {
        List<DiskImage> diskImagesToCheck =
                DisksFilter.filterImageDisks(getImagesList(), ONLY_NOT_SHAREABLE, ONLY_ACTIVE);
        DiskImagesValidator diskImagesValidator = new DiskImagesValidator(diskImagesToCheck);
        return validate(diskImagesValidator.diskImagesNotLocked());
}

13.7 虚拟机状态验证

  • 虚拟机必须为 Down 状态。
public ValidationResult vmDown() {
        if (!vm.isDown()) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_VM_IS_NOT_DOWN);
        }
        return ValidationResult.VALID;
}
  • 虚拟机的磁盘快照附加到了其他虚拟机验证。
public ValidationResult vmNotHavingDeviceSnapshotsAttachedToOtherVms(boolean onlyPlugged) {
        List<Disk> vmDisks = getDbFacade().getDiskDao().getAllForVm(vm.getId());
        ValidationResult result =
                new DiskImagesValidator(DisksFilter.filterImageDisks(vmDisks, ONLY_NOT_SHAREABLE, ONLY_ACTIVE))
                        .diskImagesSnapshotsNotAttachedToOtherVms(onlyPlugged);
        if (result != ValidationResult.VALID) {
            return result;
        }
        return ValidationResult.VALID;
}

13.8 MAC 池范围验证

  • MAC 地址池里没有足够的 MAC 地址。
private boolean canRestoreVmConfigFromSnapshot() {
        Snapshot snapshot = getSnapshot();
        return snapshot.getType() == SnapshotType.PREVIEW ?
                getSnapshotsManager().canRestoreVmConfigurationFromSnapshot(getVm(),
                        snapshot,
                        new VmInterfaceManager(getMacPool()))
                : true;
}

14 提交快照

  • 与恢复快照一致。

15 快照克隆虚拟机

  • 恢复快照使用了 AddVmFromSnapshotCommand 类。
  • 验证实现为 validate 方法。

15.1 快照相关验证

  • 快照是否存在验证。
snapshotsValidator.snapshotExists(getSnapshot())
  • 正在执行快照相关操作验证。
public ValidationResult vmNotDuringSnapshot(Guid vmId) {
        return vmNotInStatus(vmId, SnapshotStatus.LOCKED, EngineMessage.ACTION_TYPE_FAILED_VM_IS_DURING_SNAPSHOT);
}
  • 快照可用配置验证。
public ValidationResult snapshotVmConfigurationBroken(Snapshot snapshot, String vmName) {
        return !snapshot.isVmConfigurationBroken()
                ? ValidationResult.VALID
                : new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_VM_SNAPSHOT_HAS_NO_CONFIGURATION,
                String.format("$VmName %1$s", vmName),
                String.format("$SnapshotName %1$s", snapshot.getDescription()));
}
vmFromConfiguration = getVmFromConfiguration();
        if (vmFromConfiguration == null) {
            addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_VM_SNAPSHOT_HAS_NO_CONFIGURATION);
            addValidationMessageVariable("VmName", getVmName());
            addValidationMessageVariable("SnapshotName", getSnapshotName());

            return false;
}

15.2 镜像锁验证

public ValidationResult diskImagesNotLocked() {
        return diskImagesNotInStatus(ImageStatus.LOCKED, EngineMessage.ACTION_TYPE_FAILED_DISKS_LOCKED);
}

15.3 存储域验证

  • 至少存在一个激活的存储域。
storageDomainsValidator.allDomainsExistAndActive()
  • 磁盘配置与存储域类型不兼容。
public ValidationResult snapshotVmConfigurationBroken(Snapshot snapshot, String vmName) {
        return !snapshot.isVmConfigurationBroken()
                ? ValidationResult.VALID
                : new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_VM_SNAPSHOT_HAS_NO_CONFIGURATION,
                String.format("$VmName %1$s", vmName),
                String.format("$SnapshotName %1$s", snapshot.getDescription()));
}

15.4 虚拟机锁验证

public ValidationResult vmNotLocked() {
        if (vm.getStatus() == VMStatus.ImageLocked) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_VM_IS_LOCKED);
        }
        return ValidationResult.VALID;
}

15.4 创建虚拟机验证

  • 与创建虚拟机一致。

15.5 VirtIO-SCSI 磁盘验证

protected boolean checkCanDisableVirtIoScsi() {
        VmValidator vmValidator = createVmValidator(getVmFromConfiguration());
        if (Boolean.FALSE.equals(getParameters().isVirtioScsiEnabled()) &&
                !validate(vmValidator.canDisableVirtioScsi(getAdjustedDiskImagesFromConfiguration()))) {
            return false;
        } else {
            return true;
        }
}

16 创建模板

  • 恢复快照使用了 AddVmTemplateCommand 类。
  • 验证实现为 validate 方法。

16.1 群集验证

  • 群集 ID 不存在验证。
boolean isInstanceType = getParameters().getTemplateType() == VmEntityType.INSTANCE_TYPE;
if (getCluster() == null && !isInstanceType) {
    return failValidation(EngineMessage.VDS_CLUSTER_IS_NOT_VALID);
}
  • 群集不具有定义的架构。
if (getCluster().getArchitecture() == ArchitectureType.undefined) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_CLUSTER_UNDEFINED_ARCHITECTURE);
}
  • 架构操作系统支持。
if (!validate(vmHandler.isOsTypeSupported(getParameters().getMasterVm().getOsId(), getCluster().getArchitecture()))) {
       return false;
}
  • 图形显示支持。
Guid srcId = isVmInDb ? getVmId() : VmTemplateHandler.BLANK_VM_TEMPLATE_ID;
if (!validate(vmHandler.isGraphicsAndDisplaySupported(getParameters().getMasterVm().getOsId(), vmHandler.getResultingVmGraphics(getVmDeviceUtils().getGraphicsTypesOfEntity(srcId), getParameters().getGraphicsDevices()), getParameters().getMasterVm().getDefaultDisplayType(), getVm().getCompatibilityVersion()))) {
       return false;
}
  • 单显示设备验证。
    • 不能通过 VNC 设置单个显示设备。
    • 不能在非 Linux 操作系统上设置单个显示设备。
if (getParameters().getVm().getSingleQxlPci() &&
                !validate(vmHandler.isSingleQxlDeviceLegal(
                        getParameters().getVm().getDefaultDisplayType(), getParameters().getVm().getOs()))) {
            return false;
}
  • 智能卡验证。
if (!validate(vmHandler.validateSmartCardDevice(getParameters().getMasterVm()))) {
     return false;
}
  • 系统看门狗支持。
// Check if the watchdog model is supported
        if (getParameters().getWatchdog() != null) {
            if (!validate(new VmWatchdogValidator.VmWatchdogClusterDependentValidator(getParameters().getMasterVm().getOsId(),
                    getParameters().getWatchdog(),
                    getVm().getCompatibilityVersion()).isValid())) {
                return false;
            }
}
  • 所属数据中心验证。
if (!getStoragePoolId().equals(getCluster().getStoragePoolId())) {
            addValidationMessage(EngineMessage.VDS_CLUSTER_ON_DIFFERENT_STORAGE_POOL);
       return false;
}
  • 虚拟机属性验证。
if (!VmPropertiesUtils.getInstance().validateVmProperties(getVm().getCompatibilityVersion(), getParameters().getMasterVm().getCustomProperties(), getReturnValue().getValidationMessages())) {
      return false;
}

16.2 虚拟机优先级范围验证

  • 优先级范围 >=0 且 <=VmPriorityMaxValue。(默认值为 100)
public ValidationResult isVmPriorityValueLegal(int value) {
        return ValidationResult.failWith(
                EngineMessage.VM_OR_TEMPLATE_ILLEGAL_PRIORITY_VALUE,
                String.format("$MaxValue %1$s", Config.<Integer> getValue(ConfigValues.VmPriorityMaxValue))
        ).unless(value >= 0 && value <= Config.<Integer> getValue(ConfigValues.VmPriorityMaxValue));
}

16.3 虚拟机是否锁定运行验证

if (isVmInDb && !isVmStatusValid(getVm().getStatus())) {
            return failValidation(EngineMessage.VMT_CANNOT_CREATE_TEMPLATE_FROM_DOWN_VM);
}

16.4 名称重复验证

if (!isTemplateVersion()) {
            if (isInstanceType) {
                if (isInstanceWithSameNameExists(getVmTemplateName())) {
                    return failValidation(EngineMessage.ACTION_TYPE_FAILED_NAME_ALREADY_USED);
                }
            } else {
                if (isVmTemplateWithSameNameExist(getVmTemplateName(), getCluster().getStoragePoolId())) {
                    return failValidation(EngineMessage.ACTION_TYPE_FAILED_NAME_ALREADY_USED);
                }
            }
}

16.5 基础模板验证

  • 基础模板是否存在。
  • 基础模板是否可用。
if (isTemplateVersion()) {
            VmTemplate userSelectedBaseTemplate = getBaseTemplate();
            if (userSelectedBaseTemplate == null) {
                return failValidation(EngineMessage.ACTION_TYPE_FAILED_TEMPLATE_DOES_NOT_EXIST);
            } else if (!userSelectedBaseTemplate.isBaseTemplate()) {
                // currently template version cannot be base template
                return failValidation(EngineMessage.ACTION_TYPE_FAILED_TEMPLATE_VERSION_CANNOT_BE_BASE_TEMPLATE);

            }
}
  • 空模板不能有子模板。
if (isTemplateVersion() && getBaseTemplate().isBlank()) {
            return failValidation(EngineMessage.BLANK_TEMPLATE_CANT_HAVE_SUBTEMPLATES);
}

16.6 磁盘配置集设置验证

protected boolean setAndValidateDiskProfiles() {
        if (diskInfoDestinationMap != null && !diskInfoDestinationMap.isEmpty()) {
            Map<DiskImage, Guid> map = diskInfoDestinationMap.values().stream()
                    .filter(DisksFilter.ONLY_IMAGES)
                    .collect(Collectors.toMap(Function.identity(), d -> d.getStorageIds().get(0)));
            return validate(diskProfileHelper.setAndValidateDiskProfiles(map, getCurrentUser()));
        }
        return true;
}
  • 是否有配置集设置权限。
if (!updateDiskProfileForBackwardCompatibility(diskImage, diskProfilesList, permittedDiskProfilesIds, user)) {
       return new ValidationResult(EngineMessage.USER_NOT_AUTHORIZED_TO_ATTACH_DISK_PROFILE);
}
  • 存储中没有查询到定义的磁盘配置集。
DiskProfile diskProfile = updateDiskImageProfilesList(diskImage, storageDomainId);
                if (diskProfile == null) {
                    return new ValidationResult(EngineMessage.ACTION_TYPE_DISK_PROFILE_NOT_FOUND_FOR_STORAGE_DOMAIN,
                            String.format("$storageDomainId %s", storageDomainId));
}
  • 是否有权限为磁盘附加配置集。
ValidationResult result = isDiskProfileParentEntityValid(diskProfile, storageDomainId);
if (result != ValidationResult.VALID) {
        return result;
}
if (!isDiskProfilePermitted(diskProfile, permittedDiskProfilesIds, user)) {
        return new ValidationResult(EngineMessage.USER_NOT_AUTHORIZED_TO_ATTACH_DISK_PROFILE);
}

16.7 CPU 配置集设置验证

protected boolean setAndValidateCpuProfile() {
        // cpu profile isn't supported for instance types.
        if (getParameters().getTemplateType() == VmEntityType.INSTANCE_TYPE) {
            return true;
        }
        return validate(cpuProfileHelper.setAndValidateCpuProfile(
                getParameters().getMasterVm(),
                getUserIdIfExternal().orElse(null)));
}
  • 有无 CPU 配置集。
if (vmBase.getCpuProfileId() == null) {
      return assignFirstCpuProfile(vmBase, userId);
}
  • 群集不存在。
Guid clusterId =  vmBase.getClusterId();
if (clusterId == null) {
     return new ValidationResult(EngineMessage.ACTION_TYPE_CPU_PROFILE_CLUSTER_NOT_PROVIDED);
}
  • 通过 ID 查询不到 CPU 配置集。
CpuProfile fetchedCpuProfile = cpuProfileDao.get(vmBase.getCpuProfileId());
if (fetchedCpuProfile == null) {
      return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_CPU_PROFILE_NOT_FOUND);
}
  • CPU 配置集与群集不匹配。
if (!clusterId.equals(fetchedCpuProfile.getClusterId())) {
    return new ValidationResult(EngineMessage.ACTION_TYPE_CPU_PROFILE_NOT_MATCH_CLUSTER);
}
  • 有无权限分配 CPU 配置集给虚拟机。
if (!checkPermissions(vmBase.getCpuProfileId(), userId)) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_NO_PERMISSION_TO_ASSIGN_CPU_PROFILE,
                    String.format("$cpuProfileId %s",
                            vmBase.getCpuProfileId()),
                    String.format("$cpuProfileName %s",
                            fetchedCpuProfile.getName()));
}

16.8 空磁盘别名验证

protected boolean isDisksAliasNotEmpty() {
        // Check that all the template's allocated disk's aliases are not an empty string.
        for (DiskImage diskImage : diskInfoDestinationMap.values()) {
            if (StringUtils.isEmpty(diskImage.getDiskAlias())) {
                return failValidation(EngineMessage.ACTION_TYPE_FAILED_TEMPLATE_CANNOT_BE_CREATED_WITH_EMPTY_DISK_ALIAS);
            }
        }
        return true;
}

16.9 虚拟机图标验证

  • 图标是否存在。
  • 格式是否正确。
  • 图标类型是否未知。
  • 图标是否能够读取。
  • 图标 mime 类型与镜像数据是否匹配。
  • 图标维度验证。

16.9.1 大图标验证。

if (getParameters().getVmLargeIcon() != null && !validate(IconValidator.validate(IconValidator.DimensionsType.LARGE_CUSTOM_ICON, getParameters().getVmLargeIcon()))) {
     return false;
}
if (getParameters().getMasterVm().getLargeIconId() != null
                && getParameters().getVmLargeIcon() == null // icon id is ignored if large icon is sent
                && !validate(IconValidator.validateIconId(getParameters().getMasterVm().getLargeIconId(), "Large"))) {
            return false;
}

16.9.2 小图标验证。

if (getParameters().getMasterVm().getSmallIconId() != null
                && getParameters().getVmLargeIcon() == null // icon id is ignored if large icon is sent
                && !validate(IconValidator.validateIconId(getParameters().getMasterVm().getSmallIconId(), "Small"))) {
            return false;
}

16.10 看门狗验证

if (getParameters().getWatchdog() != null) {
            if (!validate(new VmWatchdogValidator.VmWatchdogClusterIndependentValidator(
                            getParameters().getWatchdog()).isValid())) {
                return false;
            }
}

16.11 内存验证

  • 最大内存限制。
if (vmBase.getMaxMemorySizeMb() < vmBase.getMemSizeMb()) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_MAX_MEMORY_CANNOT_BE_SMALLER_THAN_MEMORY_SIZE,
                    ReplacementUtils.createSetVariableString("maxMemory", vmBase.getMaxMemorySizeMb()),
                    ReplacementUtils.createSetVariableString("memory", vmBase.getMemSizeMb()));
}
  • 平台限制最大内存。
    • 32 位操作系统 VM32BitMaxMemorySizeInMB,默认 20480 M。
    • 64 位 PPC 架构 VMPpc64BitMaxMemorySizeInMB,默认 1048576 M。
    • 64 位其他架构 VM64BitMaxMemorySizeInMB,默认 4194304 M。
final int maxMemoryUpperBound = VmCommonUtils.maxMemorySizeWithHotplugInMb(vmBase.getOsId(), effectiveCompatibilityVersion);
if (vmBase.getMaxMemorySizeMb() > maxMemoryUpperBound) {
       return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_MAX_MEMORY_CANNOT_EXCEED_PLATFORM_LIMIT, ReplacementUtils.createSetVariableString("maxMemory", vmBase.getMaxMemorySizeMb()), ReplacementUtils.createSetVariableString("platformLimit", maxMemoryUpperBound));
}

16.12 封装 Windows 验证

if (getParameters().isSealTemplate() && vmHandler.isWindowsVm(getVm())) {
      return failValidation(EngineMessage.VM_TEMPLATE_CANNOT_SEAL_WINDOWS);
}

16.13 镜像验证

  • 快照是否锁定验证。
if (!validateVmNotDuringSnapshot()) {
       return false;
}
  • 存在启动的数据中心。
if (!validate(new StoragePoolValidator(getStoragePool()).existsAndUp())) {
      return false;
}
  • Cinder 磁盘最大卷数量验证。
List<CinderDisk> cinderDisks = getCinderDisks();
CinderDisksValidator cinderDisksValidator = new CinderDisksValidator(cinderDisks);
if (!validate(cinderDisksValidator.validateCinderDiskLimits())) {
      return false;
}
  • 磁盘擦除支持。
protected ValidationResult isPassDiscardSupportedForImagesDestSds() {
        Map<Disk, DiskVmElement> diskToDiskVmElement = diskHandler.getDiskToDiskVmElementMap(
                getVm().getId(), diskInfoDestinationMap);
        Map<Guid, Guid> diskIdToDestSdId = diskInfoDestinationMap.values().stream()
                .collect(Collectors.toMap(DiskImage::getId, diskImage -> diskImage.getStorageIds().get(0)));

        MultipleDiskVmElementValidator multipleDiskVmElementValidator =
                createMultipleDiskVmElementValidator(diskToDiskVmElement);
        return multipleDiskVmElementValidator.isPassDiscardSupportedForDestSds(diskIdToDestSdId);
}
  • 磁盘锁和损坏验证。
List<DiskImage> diskImagesToCheck = DisksFilter.filterImageDisks(images, ONLY_NOT_SHAREABLE, ONLY_ACTIVE); 
diskImagesToCheck.addAll(cinderDisks);
DiskImagesValidator diskImagesValidator = new DiskImagesValidator(diskImagesToCheck);
if (!validate(diskImagesValidator.diskImagesNotIllegal()) || !validate(diskImagesValidator.diskImagesNotLocked())) {
        return false;
}

16.13.1 存储域验证

  • 存储域激活验证。
MultipleStorageDomainsValidator storageDomainsValidator =
                    getStorageDomainsValidator(getStoragePoolId(), sourceImageDomainsImageMap.keySet());
if (!validate(storageDomainsValidator.allDomainsExistAndActive())) {
         return false;
}
  • 存储域存在和存储域所属数据中心一致验证。
if (storageDomainStaticDao.get(destImageDomain) == null) {
           addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_NOT_EXIST);
} else {
           addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_NOT_IN_STORAGE_POOL);
}
return false;
  • 存储域非法验证。
if (storage.getStatus() == null || storage.getStatus() != StorageDomainStatus.Active) {
                    addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_STATUS_ILLEGAL);
                    return false;
                }

                if (storage.getStorageDomainType().isIsoOrImportExportDomain()) {

                    addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_TYPE_ILLEGAL);
                    return false;
}

16.14 CPU 核数验证

  • 不同的 CPU 架构不同的核数限制。
public static ValidationResult validateCpuSockets(VmBase vmBase, Version compatibilityVersion) {
        int num_of_sockets = vmBase.getNumOfSockets();
        int cpu_per_socket = vmBase.getCpuPerSocket();
        int threadsPerCpu = vmBase.getThreadsPerCpu();

        String version = compatibilityVersion.toString();

        if ((num_of_sockets * cpu_per_socket * threadsPerCpu) >
                Config.<Integer> getValue(ConfigValues.MaxNumOfVmCpus, version)) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_MAX_NUM_CPU);
        }
        if (num_of_sockets > Config.<Integer> getValue(ConfigValues.MaxNumOfVmSockets, version)) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_MAX_NUM_SOCKETS);
        }
        if (cpu_per_socket > Config.<Integer> getValue(ConfigValues.MaxNumOfCpuPerSocket, version)) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_MAX_CPU_PER_SOCKET);
        }
        if (threadsPerCpu > Config.<Integer> getValue(ConfigValues.MaxNumOfThreadsPerCpu, version)) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_MAX_THREADS_PER_CPU);
        }
        if (cpu_per_socket < 1) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_MIN_CPU_PER_SOCKET);
        }
        if (num_of_sockets < 1) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_MIN_NUM_SOCKETS);
        }
        if (threadsPerCpu < 1) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_MIN_THREADS_PER_CPU);
        }
        return ValidationResult.VALID;
}

17 模板创建虚拟机

  • 模板创建虚拟机使用了 AddVmFromTemplateCommand 类。
  • 验证实现为 validate 方法。

17.1 创建虚拟机验证。

  • 与 6 创建虚拟机验证一致。

17.2 磁盘配置与存储域类型兼容验证

List<DiskImage> templateDiskImages = DisksFilter.filterImageDisks(getVmTemplate().getDiskTemplateMap().values(), ONLY_NOT_SHAREABLE);
for (DiskImage dit : templateDiskImages) {
            DiskImage diskImage = diskInfoDestinationMap.get(dit.getId());
            if (!ImagesHandler.checkImageConfiguration(
                    destStorages.get(diskImage.getStorageIds().get(0)).getStorageStaticData(),
                    diskImage,
                    getReturnValue().getValidationMessages())) {
                return false;
            }
}

18 导出虚拟机

  • 导出虚拟机使用了 ExportVmCommand 类。
  • 验证实现为 validate 方法。

18.1 虚拟机为空验证

if (getVm() == null) {
       return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_NOT_FOUND);
}

18.2 存储域验证

  • 存储域存在并激活验证。
StorageDomainValidator targetstorageDomainValidator = new StorageDomainValidator(getStorageDomain());
if (!validate(targetstorageDomainValidator.isDomainExistAndActive())) {
       return false;
}

18.3 镜像加锁验证

List<DiskImage> disksForExport = getDisksBasedOnImage();
DiskImagesValidator diskImagesValidator = new DiskImagesValidator(disksForExport);
if (!validate(diskImagesValidator.diskImagesNotIllegal()) || !validate(diskImagesValidator.diskImagesNotLocked())) {
    return false;
}

18.4 存储域验证

  • 目标存储域不在数据中心内。
// check that the target and source domain are in the same storage_pool
if (storagePoolIsoMapDao.get(new StoragePoolIsoMapId(getStorageDomain().getId(), getVm().getStoragePoolId())) == null) {
     return failValidation(EngineMessage.ACTION_TYPE_FAILED_STORAGE_POOL_NOT_MATCH);
}

18.4 模板验证

  • 模板不存在导出域中。
    • 如果只导出虚拟机,而不导出依赖的模板,那么需要设置 TemplateMustExists=false
if (getParameters().getTemplateMustExists()) {
            if (!checkTemplateInStorageDomain(getVm().getStoragePoolId(), getParameters().getStorageDomainId(),
                    getVm().getVmtGuid(), getContext().getEngineContext())) {
                return failValidation(EngineMessage.ACTION_TYPE_FAILED_TEMPLATE_NOT_FOUND_ON_EXPORT_DOMAIN,
                        String.format("$TemplateName %1$s", getVm().getVmtName()));
            }
}

18.5 导出格式验证

  • 在导出虚拟机上无法把格式修改为 RAW
Map<Guid, ? extends Disk> images = getVm().getDiskMap();
        if (getParameters().getCopyCollapse()) {
            for (DiskImage img : disksForExport) {
                if (images.containsKey(img.getId())) {
                    // check that no RAW format exists (we are in collapse mode)
                    if (((DiskImage) images.get(img.getId())).getVolumeFormat() == VolumeFormat.RAW
                            && img.getVolumeFormat() != VolumeFormat.RAW) {
                        return failValidation(EngineMessage.VM_CANNOT_EXPORT_RAW_FORMAT);
                    }
                }
            }
}

18.6 导出域验证

  • 指定的域不是一个导出域。
if (getStorageDomain().getStorageDomainType() != StorageDomainType.ImportExport) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_SPECIFY_DOMAIN_IS_NOT_EXPORT_DOMAIN, String.format("$storageDomainName %1$s", getStorageDomainName()));
}
  • 存储域剩余空间验证。
private boolean handleDestStorageDomain(List<DiskImage> disksList) {
        ensureDomainMap(disksList, getStorageDomainId());
        List<DiskImage> dummiesDisksList = createDiskDummiesForSpaceValidations(disksList);
        dummiesDisksList.addAll(getMemoryVolumes());
        return validateSpaceRequirements(dummiesDisksList);
}
  • 虚拟机名称重复验证
protected boolean checkVmInStorageDomain() {
        GetAllFromExportDomainQueryParameters tempVar = new GetAllFromExportDomainQueryParameters(getVm()
                .getStoragePoolId(), getParameters().getStorageDomainId());
        QueryReturnValue qretVal = runInternalQuery(QueryType.GetVmsFromExportDomain,
                tempVar);

        if (qretVal.getSucceeded()) {
            List<VM> vms = qretVal.getReturnValue();
            for (VM vm : vms) {
                if (vm.getId().equals(getVm().getId())) {
                    if (!getParameters().getForceOverride()) {
                        return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_GUID_ALREADY_EXIST);
                    }
                } else if (vm.getName().equals(getVm().getName())) {
                    return failValidation(EngineMessage.ACTION_TYPE_FAILED_NAME_ALREADY_USED);
                }
            }
        }
        return true;
}
  • 存储域必须存在并激活状态。
new MultipleStorageDomainsValidator(getVm().getStoragePoolId(), ImagesHandler.getAllStorageIdsForImageIds(disksForExport)).allDomainsExistAndActive()))

18.7 数据中心验证

  • 数据中心必须存在并处于激活状态。
new StoragePoolValidator(getStoragePool()).existsAndUp()

18.8 快照验证

  • 镜像是否正在被使用。
snapshotsValidator.vmNotDuringSnapshot(getVmId())
  • 不存在预览状态的快照。
snapshotsValidator.vmNotInPreview(getVmId())

18.9 虚拟机状态验证

  • 虚拟机是否存于关机状态。
new VmValidator(getVm()).vmDown()

19 导入虚拟机

  • 导入虚拟机使用了 ImportVmCommand 类。
  • 验证实现为 validate 方法。

19.1 虚拟机为空验证

if (getVm() == null) {
       return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_NOT_FOUND);
}

19.2 群集验证

  • 群集是否存在。
if (getCluster() == null) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_CLUSTER_CAN_NOT_BE_EMPTY);
}
  • 群集 ID 是否存在。
if (getParameters().getStoragePoolId() != null
                && !getParameters().getStoragePoolId().equals(getCluster().getStoragePoolId())) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_CLUSTER_IS_NOT_VALID);
}

19.3 MAC 池验证

  • 不允许导入可能会在目标 MAC 池中造成重复的虚拟机。
List<VmNetworkInterface> nicsUnableToBeImported = getVm().getInterfaces()
                .stream()
                .filter(this::ifaceMacCannotBeAddedToMacPool)
                .collect(Collectors.toList());

        if (!nicsUnableToBeImported.isEmpty()) {
            EngineMessage engineMessage = EngineMessage.ACTION_TYPE_FAILED_CANNOT_ADD_IFACE_DUE_TO_MAC_DUPLICATES;
            Collection<String> replacements =
                    ReplacementUtils.getListVariableAssignmentString(engineMessage, nicsUnableToBeImported);

            return validate(new ValidationResult(engineMessage, replacements));
}
  • 导入后 MAC 地址池里没有足够的 MAC 地址。
if (getParameters().isImportAsNewEntity()) {
            initImportClonedVm();

            if (getVm().getInterfaces().size() > getMacPool().getAvailableMacsCount()) {
                return failValidation(EngineMessage.MAC_POOL_NOT_ENOUGH_MAC_ADDRESSES);
            }
}

19.4 cloud-init 配置验证

  • cloud-init 配置中的 Start On Boot 只支持 true。
  • cloud-init 配置中缺少了静态 IPv4 地址。
  • cloud-init 配置中缺少了静态 IPv6 地址。
  • cloud-init 配置中的选项 'autoconf' 不被支持。
public List<EngineMessage> validate(VmInit vmInit) {
        if (vmInit == null || vmInit.getNetworks() == null) {
            return null;
        }

        List<EngineMessage> msgs = new LinkedList<>();
        List<VmInitNetwork> vmInitNetworks = vmInit.getNetworks();
        for (VmInitNetwork vmInitNetwork : vmInitNetworks) {
            if (!isStartOnBoot(vmInitNetwork)) {
                msgs.add(EngineMessage.VALIDATION_CLOUD_INIT_START_ON_BOOT_INVALID);
            }
            if (isStaticIPv4AndAddressMissing(vmInitNetwork)) {
                msgs.add(EngineMessage.VALIDATION_CLOUD_INIT_STATIC_IPV4_ADDRESS_MISSING);
            }
            if (isStaticIPv6AndAddressMissing(vmInitNetwork)) {
                msgs.add(EngineMessage.VALIDATION_CLOUD_INIT_STATIC_IPV6_ADDRESS_MISSING);
            }
            if (isAutoConfIPv6(vmInitNetwork)) {
                msgs.add(EngineMessage.VALIDATION_CLOUD_INIT_IPV6_AUTOCONF_UNSUPPORTED);
            }
        }
        return msgs;
}

19.5 导入前验证

Map<Guid, StorageDomain> domainsMap = new HashMap<>();
if (!validateBeforeCloneVm(domainsMap)) {
       return false;
}

19.5.1 数据中心验证

  • 数据中心存在并激活状态。
StoragePoolValidator spValidator = new StoragePoolValidator(getStoragePool());
if (!validate(spValidator.existsAndUp())) {
       return false;
}

19.5.2 存储域验证

  • 存储域存在并激活状态。
  • 目的域类型非法。
Set<Guid> destGuids = new HashSet<>(imageToDestinationDomainMap.values());
        for (Guid destGuid : destGuids) {
            StorageDomain storageDomain = getStorageDomain(destGuid);
            StorageDomainValidator validator = new StorageDomainValidator(storageDomain);
            if (!validate(validator.isDomainExistAndActive()) || !validate(validator.domainIsValidDestination())) {
                return false;
            }

            domainsMap.put(destGuid, storageDomain);
}

19.5.3 快照验证

  • 导出域中虚拟机存在快照的情况,需要考虑存在被 collapse 的快照。
if (!isImagesAlreadyOnTarget() && getParameters().isImportAsNewEntity()
                && isCopyCollapseDisabledWithSnapshotsOrWithTemplate()) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_IMPORT_CLONE_NOT_COLLAPSED,
                    String.format("$VmName %1$s", getVmName()));
}
  • 没有注册的虚拟机不能被 collapse。
if (isImagesAlreadyOnTarget() && getParameters().getCopyCollapse()) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_IMPORT_UNREGISTERED_NOT_COLLAPSED);
}

19.5.4 导出域验证

  • 非法存储域类型。
  • 导出域中不包含该虚拟机。
if (!isImagesAlreadyOnTarget()) {
            setSourceDomainId(getParameters().getSourceDomainId());
            StorageDomainValidator validator = new StorageDomainValidator(getSourceDomain());
            if (validator.isDomainExistAndActive().isValid()
                    && getSourceDomain().getStorageDomainType() != StorageDomainType.ImportExport) {
                return failValidation(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_TYPE_ILLEGAL);
            }
            if (!validateAndSetVmFromExportDomain()) {
                return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_NOT_FOUND_ON_EXPORT_DOMAIN);
            }
}

19.5.5 镜像验证

if (!validateImages(domainsMap)) {
        return false;
}

19.6 内存气球支持

protected boolean validateBallonDevice() {
        if (!VmDeviceCommonUtils.isBalloonDeviceExists(getVm().getManagedVmDeviceMap().values())) {
            return true;
        }

        if (!osRepository.isBalloonEnabled(getVm().getStaticData().getOsId(),
                getEffectiveCompatibilityVersion())) {
            addValidationMessageVariable("clusterArch", getCluster().getArchitecture());
            return failValidation(EngineMessage.BALLOON_REQUESTED_ON_NOT_SUPPORTED_ARCH);
        }

        return true;
}

19.7 音频设备支持

protected boolean validateSoundDevice() {
        if (!VmDeviceCommonUtils.isSoundDeviceExists(getVm().getManagedVmDeviceMap().values())) {
            return true;
        }

        if (!osRepository.isSoundDeviceEnabled(getVm().getStaticData().getOsId(),
                getEffectiveCompatibilityVersion())) {
            addValidationMessageVariable("clusterArch", getCluster().getArchitecture());
            return failValidation(EngineMessage.SOUND_DEVICE_REQUESTED_ON_NOT_SUPPORTED_ARCH);
        }

        return true;
}

19.8 内存验证

  • 与 16.11 内存验证一致。

19.9 导入后验证

19.9.1 虚拟机 ID 是否存在

if (!validateNoDuplicateVm()) {
            return false;
}

19.9.2 磁盘是否存在

public ValidationResult diskImagesAlreadyExist() {

        List<String> existingDisksAliases = new ArrayList<>();
        for (DiskImage diskImage : diskImages) {
            DiskImage existingDisk = getExistingDisk(diskImage.getId());
            if (existingDisk != null) {
                existingDisksAliases.add(diskImage.getDiskAlias().isEmpty() ? existingDisk.getDiskAlias() : diskImage.getDiskAlias());
            }
        }

        if (!existingDisksAliases.isEmpty()) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_IMPORT_DISKS_ALREADY_EXIST,
                    String.format("$diskAliases %s", StringUtils.join(existingDisksAliases, ", ")));
        }

        return ValidationResult.VALID;
}

19.9.3 模板验证

  • 模板是否存在。
private boolean templateExists() {
        if (getVmTemplate() == null && !getParameters().getCopyCollapse()) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_TEMPLATE_DOES_NOT_EXIST);
        }
        return true;
}
  • 所选的存储域是否包含虚拟机模板。
protected boolean checkTemplateInStorageDomain() {
        boolean retValue = validate(getImportValidator().verifyDisks(imageList, imageToDestinationDomainMap));
        if (retValue && !VmTemplateHandler.BLANK_VM_TEMPLATE_ID.equals(getVm().getVmtGuid())
                && !getParameters().getCopyCollapse()) {
            List<StorageDomain> domains = runInternalQuery(QueryType.GetStorageDomainsByVmTemplateId,
                    new IdQueryParameters(getVm().getVmtGuid())).getReturnValue();
            Set<Guid> domainsId = domains.stream().map(StorageDomain::getId).collect(Collectors.toSet());

            if (!domainsId.isEmpty() && Collections.disjoint(domainsId, imageToDestinationDomainMap.values())) {
                return failValidation(EngineMessage.ACTION_TYPE_FAILED_TEMPLATE_NOT_FOUND_ON_DESTINATION_DOMAIN);
            }
        }
        return retValue;
}
  • 模板锁验证。
if (!VmTemplateHandler.BLANK_VM_TEMPLATE_ID.equals(getVm().getVmtGuid())
                && getVmTemplate() != null
                && getVmTemplate().getStatus() == VmTemplateStatus.Locked) {
            return failValidation(EngineMessage.VM_TEMPLATE_IMAGE_IS_LOCKED);
}
  • 缺失导出域中模板。
if (getParameters().getCopyCollapse() && !isTemplateExistsOnExportDomain()) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_IMPORTED_TEMPLATE_IS_MISSING,
                    String.format("$DomainName %1$s",
                            storageDomainStaticDao.get(getParameters().getSourceDomainId()).getStorageName()));
}

19.9.4 镜像验证

  • 虚拟机镜像是否存在。
protected boolean checkImagesGUIDsLegal() {
        for (DiskImage image : new ArrayList<>(getImages())) {
            Guid imageGUID = image.getImageId();
            Guid storagePoolId = image.getStoragePoolId() != null ? image.getStoragePoolId()
                    : Guid.Empty;
            Guid storageDomainId = getSourceDomainId(image);
            Guid imageGroupId = image.getId() != null ? image.getId() : Guid.Empty;

            VDSReturnValue retValue = runVdsCommand(
                    VDSCommandType.GetImageInfo,
                    new GetImageInfoVDSCommandParameters(storagePoolId, storageDomainId, imageGroupId,
                            imageGUID));

            if (!retValue.getSucceeded()) {
                if (!getParameters().isAllowPartialImport()) {
                    return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_IMAGE_DOES_NOT_EXIST);
                }
                log.warn("Disk image '{}/{}' doesn't exist on storage domain '{}'. Ignoring since force flag in on",
                        imageGroupId,
                        imageGUID,
                        storageDomainId);
                getVm().getImages().remove(image);
                failedDisksToImportForAuditLog.putIfAbsent(image.getId(), image.getDiskAlias());
            }
        }
        return true;
}

19.9.5 虚拟机名称验证

  • 虚拟机名称重复。
protected boolean validateUniqueVmName() {
        return vmHandler.isVmWithSameNameExistStatic(getVm().getName(), getStoragePoolId()) ?
                failValidation(EngineMessage.VM_CANNOT_IMPORT_VM_NAME_EXISTS)
                : true;
}

19.9.6 Lun 磁盘验证

if (!validateLunDisksForVm(vmFromParams)) {
      return false;
}

19.9.7 磁盘配置与存储域类型兼容验证

  • 与 17.2 磁盘配置与存储域类型兼容验证一致。

19.9.8 虚拟机架构验证

protected boolean validateVmArchitecture () {
        return getVm().getClusterArch() == ArchitectureType.undefined ?
            failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_CANNOT_IMPORT_VM_WITH_NOT_SUPPORTED_ARCHITECTURE)
            : true;
}

19.9.9 群集验证

  • 群集是否存在。
  • 群集是否支持虚拟机架构。
protected boolean validateVdsCluster() {
        Cluster cluster = clusterDao.get(getClusterId());
        return cluster == null ?
                failValidation(EngineMessage.VDS_CLUSTER_IS_NOT_VALID)
                : cluster.getArchitecture() != getVm().getClusterArch() ?
                        failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_CANNOT_IMPORT_VM_ARCHITECTURE_NOT_SUPPORTED_BY_CLUSTER)
                        : true;
}

19.9.10 目的域空间验证

protected boolean handleDestStorageDomains() {
        List<DiskImage> dummiesDisksList = createDiskDummiesForSpaceValidations(imageList);
        if (getParameters().getCopyCollapse()) {
            Snapshot activeSnapshot = getActiveSnapshot();
            if (activeSnapshot != null && activeSnapshot.containsMemory()) {
                // Checking space for memory volume of the active image (if there is one)
                StorageDomain storageDomain = findDomainForMemoryImagesAndCreateDummies(dummiesDisksList);
                if (storageDomain == null) {
                    return failValidation(EngineMessage.ACTION_TYPE_FAILED_NO_SUITABLE_DOMAIN_FOUND);
                }
            }
        } else { // Check space for all the snapshot's memory volumes
            if (!determineDomainsForMemoryImagesAndCreateDummies(dummiesDisksList)) {
                return false;
            }
        }
        return validate(getImportValidator().validateSpaceRequirements(dummiesDisksList));
}

19.9.11 图形显示验证

protected boolean validateGraphicsAndDisplay() {
        return validate(vmHandler.isGraphicsAndDisplaySupported(getParameters().getVm().getOs(),
                getGraphicsTypesForVm(),
                getVm().getDefaultDisplayType(),
                getEffectiveCompatibilityVersion()));
}

19.9.12 磁盘配置集设置验证

  • 与 16.6 磁盘配置集设置验证一致。

19.9.13 CPU 配置集设置验证

  • 与 16.7 CPU 配置集设置验证一致。

19.9.14 MAC 地址格式验证

if (!getParameters().isImportAsNewEntity()) {
            List<VmNetworkInterface> vmNetworkInterfaces = getVm().getInterfaces();
            if (!validate(vmNicMacsUtils.validateThereIsEnoughOfFreeMacs(vmNetworkInterfaces,
                    getMacPool(),
                    getVnicRequiresNewMacPredicate()))) {
                return false;
            }

            if (!validate(vmNicMacsUtils.validateMacAddress(vmNetworkInterfaces))) {
                return false;
            }
}

20 导出模板

  • 导出模板使用了 ImportVmTemplateCommand 类。
  • 验证实现为 validate 方法。

20.1 模板是否存在验证

if (getVmTemplate() == null) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_TEMPLATE_DOES_NOT_EXIST);
}

20.2 存储域验证

  • 存储域存在并且激活状态。
StorageDomainValidator storageDomainValidator = new StorageDomainValidator(getStorageDomain());
if (!validate(storageDomainValidator.isDomainExistAndActive())) {
       return false;
}
  • 存储域磁盘空间验证。
sdValidator.isDomainWithinThresholds()
  • 存储域已经包含了目标磁盘。
checkIfDisksExist(getTemplateDisks()))
  • 目的域空间是否足够。
validateFreeSpaceOnDestinationDomain(sdValidator, getTemplateDisks())
  • 指定的域不是一个导出域。
if (getStorageDomain().getStorageDomainType() != StorageDomainType.ImportExport) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_SPECIFY_DOMAIN_IS_NOT_EXPORT_DOMAIN);
}

20.3 镜像验证

  • 镜像是否存在。
  • 镜像是否加锁。
  • 镜像是否损坏。
vmTemplateHandler.isVmTemplateImagesReady(getVmTemplate(), null, true, true, true, false, getTemplateDisks()))

20.4 模板验证

  • 目标域中未包含该模板。
if (storagePoolIsoMapDao.get(new StoragePoolIsoMapId(getStorageDomain().getId(),
                            getVmTemplate().getStoragePoolId())) == null) {
                return failValidation(EngineMessage.ACTION_TYPE_FAILED_STORAGE_POOL_NOT_MATCH);
}
  • 目标域中模板名称重复。
if (!getParameters().getForceOverride()) {
            if (ExportVmCommand.checkTemplateInStorageDomain(getVmTemplate().getStoragePoolId(),
                    getParameters().getStorageDomainId(), getVmTemplateId(), getContext().getEngineContext())) {
                return failValidation(EngineMessage.ACTION_TYPE_FAILED_NAME_ALREADY_USED);
            }
}

21 导入模板

  • 导入模板使用了 ImportVmTemplateCommand 类。
  • 验证实现为 validate 方法。

21.1 模板是否存在验证

if (getVmTemplate() == null) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_TEMPLATE_DOES_NOT_EXIST);
}

21.2 群集验证

  • 群集是否存在验证。
if (getCluster() == null) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_CLUSTER_CAN_NOT_BE_EMPTY);
}
  • 群集 ID 是否存在验证。
if (!getCluster().getStoragePoolId().equals(getStoragePoolId())) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_CLUSTER_IS_NOT_VALID);
}

21.3 数据中心验证

  • 数据中心存在并且激活状态。
createStoragePoolValidator().existsAndUp()

21.4 模板架构验证

  • 模板架构验证。
protected boolean validateTemplateArchitecture () {
        if (getVmTemplate().getClusterArch() == ArchitectureType.undefined) {
            addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_VM_CANNOT_IMPORT_TEMPLATE_WITH_NOT_SUPPORTED_ARCHITECTURE);
            return false;
        }
        return true;
}
  • 群集是否支持该模板架构验证。
protected boolean isClusterCompatible () {
        if (getCluster().getArchitecture() != getVmTemplate().getClusterArch()) {
            addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_VM_CANNOT_IMPORT_TEMPLATE_ARCHITECTURE_NOT_SUPPORTED_BY_CLUSTER);
            return false;
        }
        return true;
}

21.5 源存储域验证

setSourceDomainId(getParameters().getSourceDomainId());
if (!validateSourceStorageDomain()) {
        return false;
}

21.6 模板验证

  • 模板名称重复。
if (getVmTemplate().isBaseTemplate() && isVmTemplateWithSameNameExist()) {
            return failValidation(EngineMessage.VM_CANNOT_IMPORT_TEMPLATE_NAME_EXISTS);
}
  • 模板 ID 重复。
VmTemplate duplicateTemplate = vmTemplateDao.get(getParameters().getVmTemplate().getId());
        // check that the template does not exists in the target domain
        if (duplicateTemplate != null) {
            return failValidation(EngineMessage.VMT_CANNOT_IMPORT_TEMPLATE_EXISTS,
                    String.format("$TemplateName %1$s", duplicateTemplate.getName()));
}

21.7 磁盘空间验证

if (!validateNoDuplicateDiskImages(getImages())) {
       return false;
}

21.8 存储域空间验证

if (getImages() != null && !getImages().isEmpty() && !getParameters().isImagesExistOnTargetStorageDomain()) {
            if (!validateSpaceRequirements(getImages())) {
                return false;
            }
}

21.9 MAC 地址格式验证

List<VmNetworkInterface> vmNetworkInterfaces = getVmTemplate().getInterfaces();
vmNicMacsUtils.replaceInvalidEmptyStringMacAddressesWithNull(vmNetworkInterfaces);
if (!validate(vmNicMacsUtils.validateMacAddress(vmNetworkInterfaces))) {
            return false;
}

21.10 基础模板验证

  • 缺失模板的基础模板。
if (!getVmTemplate().isBaseTemplate()) {
            VmTemplate baseTemplate = vmTemplateDao.get(getVmTemplate().getBaseTemplateId());
            if (baseTemplate == null) {
                return failValidation(EngineMessage.VMT_CANNOT_IMPORT_TEMPLATE_VERSION_MISSING_BASE);
            }
}

21.11 磁盘配置集设置验证

  • 与 16.6 磁盘配置集设置验证一致。

21.12 CPU 配置集设置验证

  • 与 16.7 CPU 配置集设置验证一致。

21.13 内存验证

  • 与 16.11 内存验证一致。

21.14 cloud-init 配置验证

  • 与 19.4 cloud-init 配置验证一致。

相关文章

网友评论

    本文标题:【Ovirt 笔记】虚拟机相关业务验证分析与整理(2)

    本文链接:https://www.haomeiwen.com/subject/blhgaftx.html