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

文前说明

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

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

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

  • engine 中的业务执行大部分都是通过 GWT-RPC 执行后端 Command 命令实现的。
    • 通过 Backend 提供的 runInternalActionrunMultipleActions 等方法执行。
    • 例如运行虚拟机为 RunVmCommand、删除虚拟机为 RemoveVmCommand 等。
  • 执行每一个 Command 命令前,都会对执行命令的前置条件进行验证操作。
    • 3.4 中为 canDoAction
    • 4.2 中为 validate
  • 不同的 Command 的验证方法有不同的实现(多态)。
// CommandBase.java
protected boolean validate() {
     return true;
}

1. 运行虚拟机

  • 运行虚拟机使用了 RunVmCommand 类。
  • 验证实现为 validateImpl 方法。

1.1 虚拟机为空验证

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

1.2 虚拟机对象的属性验证

  • 使用了 validation beanHibernate Validator
    • validation bean 是基于JSR-303 标准开发出来的,使用注解方式实现。但是这只是一个接口,没有具体实现。
    • Hibernate Validator 是一个 hibernate 独立的包,可以直接引用,实现了接口同时又做了一些扩展。


      org.hibernate
      hibernate-validator

  • javax.validation.constraints 包中包含了验证的注解。
序号 注解 说明 可修饰对象
1 @Null 被注解的元素必须为 Null。 任意类型。
2 @NotNull 被注解的元素不能为 Null。 任意类型。
3 @AssertTrue 被注解的元素必须为 True。 Boolean、boolean
4 @AssertFalse 被注解的元素必须为 False。 Boolean、boolean
5 @Min(value) 被注解的元素必须是一个数字,并且大于等于被指定的值(value)。 BigDecimal、BigInteger、byte、short、int、long 等任何 Number 或CharSequence(存储的是数字)子类型。
6 @Max(value) 被注解的元素必须是一个数字,并且小于等于被指定的值(value)。 与 @Min 一致。
7 @DecimalMin(value) 被注解的元素必须是一个数字,并且大于等于被指定的值(value)。 与 @Min 一致。
8 @DecimalMax(value) 被注解的元素必须是一个数字,并且小于等于被指定的值(value)。 与 @Min 一致。
9 @Size(max,min) 被注解的元素必须是一个数字,并且在指定范围内。 字符串、Collection、Map、数组等。
10 @Digits(integer,fraction) 被注解的元素的整数位和小数位限制。 与 @Min 一致。
11 @Past 被注解的元素(日期类型)比当前时间早。 java.util.Date、java.util.Calendar、Joda Time 类库的日期类型。
12 @Future 被注解的元素(日期类型)比当前时间晚。 与 @Past 一致。
13 @Pattern(regexp) 被注解的元素必须符合正则表达式。 String、任何 CharSequence 的子类型。
  • 针对 @Pattern 注解,可以设置 flag 标识不同的模式。
模式 说明
UNIX_LINES 只有 " \n " 才被认作一行的中止,并且与 " . "、" ^ " 以及 " $ " 进行匹配。
CASE_INSENSITIVE 表达式忽略大小写进行匹配。
COMMENTS 匹配时会忽略(正则表达式里的)空格字符(不是指表达式里的 " \s ",而是指表达式里的空格,tab,回车之类)。
DOTALL 表达式 " . " 可以匹配任意字符,包括表示一行的结束符。默认情况下,表达式 " . " 不匹配行的结束符。
MULTILINE " ^ " 和 " " 也匹配字符串的结束。默认情况下,这两个表达式仅仅匹配字符串的开始和结束。
UNICODE_CASE 如果还启用了 CASE_INSENSITIVE 模式,那么会对 Unicode 字符进行大小写不明感的匹配。默认大小写不敏感的匹配只适用于 US-ASCII 字符集。
  • Hibernate validator 在 JSR-303 的基础上对校验注解进行了扩展。
序号 注解 说明 可修饰对象
1 @Email(regexp) 注解的元素是 Email,也可以通过 regexp 和 flag 指定自定义的 email 格式。 CharSequence子类型(如 String)。
2 @Length(min,max) 注解的元素长度在 min 和 max 区间内。 CharSequence 子类型。
3 @NotEmpty 注解的元素不为 Null 且不为空、字符串长度不能为 0、集合大小不能为 0) CharSequence 子类型、Collection、Map、数组。
4 @Range(min,max) 注解的元素在最小值和最大值之间 BigDecimal、BigInteger、CharSequence、byte、short、int、 long 等原子类型和包装类型。
  • 自定义注解
@Target({ ANNOTATION_TYPE, METHOD, FIELD, CONSTRUCTOR, PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Pattern(regexp = ValidationUtils.NO_SPECIAL_CHARACTERS_I18N)
@Constraint(validatedBy = {})
@ReportAsSingleViolation
public @interface ValidI18NName {
    String message() default "VALIDATION_FIELD_CONTAINS_SPECIAL_CHARACTERS";

    Class[] groups() default {};

    Class[] payload() default {};
}
  • 属性验证
if (!validateObject(vm.getStaticData())) {
      return false;
}
序号 属性 说明
1 validatedBy 指定验证规则的实现类。
2 message 自定义验证未通过的错误信息。
3 groups 自定义组(用于不同业务场景的验证分组)。如 CreateEntity 和 UpdateEntity 分别为创建和修改时的验证。

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

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

1.4 虚拟机版本验证

if (getVm().getCustomCompatibilityVersion() != null && vm.getCustomCompatibilityVersion().less(getStoragePool().getCompatibilityVersion())) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_COMATIBILITY_VERSION_NOT_SUPPORTED,
                    String.format("$VmName %1$s", getVm().getName()),
                    String.format("$VmVersion %1$s", getVm().getCustomCompatibilityVersion().toString()),
                    String.format("$DcVersion %1$s", getStoragePool().getCompatibilityVersion()));
}

1.5 虚拟机可运行验证

1.5.1 普通运行验证

1.5.1.1 虚拟机自定义属性验证

  • 自定义属性从 PredefinedVMPropertiesUserDefinedVMProperties 获取。
validateVmProperties(vm, messages)

1.5.1.2 引导序列的驱动验证

  • 验证硬盘启动,硬盘是否为空。
  • 验证网卡启动,是否设置了虚拟机网络。
validateBootSequence(vm, getVmDisks())

1.5.1.3 系统图形显示支持验证

private ValidationResult validateDisplayType() {
        if (!vmValidationUtils.isGraphicsAndDisplaySupported(vm.getOs(),
                vm.getCompatibilityVersion(),
                getVmActiveGraphics(),
                vm.getDefaultDisplayType())) {
                return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_ILLEGAL_VM_DISPLAY_TYPE_IS_NOT_SUPPORTED_BY_OS);
        }

        return ValidationResult.VALID;
}

1.5.1.4 虚拟机锁验证

  • 虚拟机对象是否被资源加锁。
new VmValidator(vm).vmNotLocked()

1.5.1.5 虚拟机快照锁验证。

snapshotsValidator.vmNotDuringSnapshot(vm.getId())

1.5.1.6 虚拟机状态验证

  • 验证虚拟机现阶段状态是否为可以运行的状态。
private ValidationResult validateVmStatusUsingMatrix(VM vm) {
        if (!ActionUtils.canExecute(Collections.singletonList(vm), VM.class,
                ActionType.RunVm)) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_VM_STATUS_ILLEGAL, LocalizedVmStatus.from(vm.getStatus()));
        }

        return ValidationResult.VALID;
}

1.5.1.7 数据中心状态验证

  • 直接验证通过
    • 虚拟机没有磁盘。
    • 虚拟机设置为高可用。
  • 验证数据中心状态是否为启用状态。
validateStoragePoolUp(vm, storagePool, getVmImageDisks())

1.5.1.8 ISO 与软盘文件路径验证

validateIsoPath(vm, runVmParam.getDiskPath(), runVmParam.getFloppyPath(), activeIsoDomainId)

1.5.1.9 虚拟机是否正在启动验证

  • 验证是否包含在虚拟机运行列表中。
vmDuringInitialization(vm)
Set asyncRunningVms = Collections.newSetFromMap(new ConcurrentHashMap<>());

1.5.1.10 虚拟机无状态验证

  • 如果虚拟机不是无状态的,则直接通过验证。
  • 无状态虚拟机不能设置高可用。
  • 无状态虚拟机必须有足够的空间创建快照。
validateStatelessVm(vm, runVmParam.getRunAsStateless())

1.5.1.11 软盘设备系统支持验证

private ValidationResult validateFloppy() {

        if (StringUtils.isNotEmpty(runVmParam.getFloppyPath())
                && !vmValidationUtils.isFloppySupported(vm.getOs(), vm.getCompatibilityVersion())) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_ILLEGAL_FLOPPY_IS_NOT_SUPPORTED_BY_OS);
        }

        return ValidationResult.VALID;
}

1.5.1.12 存储域验证

  • 是否存在激活状态的存储域。
  • 存储域空间是否低于最小要求。
validateStorageDomains(vm, isInternalExecution, filterReadOnlyAndPreallocatedDisks(getVmImageDisks()))

1.5.1.13 虚拟机磁盘镜像锁验证

private ValidationResult validateImagesForRunVm(VM vm, List vmDisks) {
        if (vmDisks.isEmpty()) {
            return ValidationResult.VALID;
        }

        return !vm.isAutoStartup() ?
                new DiskImagesValidator(vmDisks).diskImagesNotLocked() : ValidationResult.VALID;
}

1.5.1.14 磁盘擦除功能支持验证

  • 只有 VirtIO-SCSI 和 IDE 磁盘接口支持。
validateDisksPassDiscard(vm)

1.5.1.15 虚拟机内存验证

  • 内存大小不能超过集群版本所支持的最大内存。
protected ValidationResult validateMemorySize(VM vm) {
        int maxSize = VmCommonUtils.maxMemorySizeWithHotplugInMb(vm);
        if (vm.getMemSizeMb() > maxSize) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_MEMORY_EXCEEDS_SUPPORTED_LIMIT);
        }
        return ValidationResult.VALID;
}

1.5.1.16 可运行的主机验证

  • 根据群集策略选择可运行主机,没有则给出错误提示。
!getSchedulingManager().canSchedule(cluster, vm, vdsBlackList, vdsWhiteList, messages).isEmpty()

1.5.2 暂停后运行

  • 暂停后运行只需要验证主机状态。
    • 主机必须为启动状态。
private ValidationResult validateVdsStatus(VM vm) {
        if (vm.getStatus() == VMStatus.Paused && vm.getRunOnVds() != null &&
                getVdsDynamic(vm.getRunOnVds()).getStatus() != VDSStatus.Up) {
            return new ValidationResult(
                    EngineMessage.ACTION_TYPE_FAILED_VDS_STATUS_ILLEGAL,
                    EngineMessage.VAR__HOST_STATUS__UP.toString());
        }

        return ValidationResult.VALID;
}

1.5.3 挂起后运行

  • 挂起后运行与普通运行的验证基本一致。
    • 不执行虚拟机自定义属性验证。
    • 不执行引导序列的驱动验证。
    • 不执行系统图形显示支持验证。
    • 不执行 ISO 与软盘文件路径验证。
    • 不执行虚拟机无状态验证。
    • 不执行软盘设备系统支持验证。
    • 不执行虚拟机内存验证。

1.6 虚拟机网络验证

  • 验证配置的虚拟网络是否属于所在群集。
  • 配置的网络必须为存在的虚拟网络。
if (!validate(runVmValidator.validateNetworkInterfaces())) {
     return false;
}

1.7 虚拟机租赁验证

  • 虚拟机租赁的目标存储域状态必须存在并激活。
  • 选择了租赁目标存储域,则必须包含租赁信息。
public ValidationResult validateVmLease() {
        if (vm.getLeaseStorageDomainId() == null) {
            return ValidationResult.VALID;
        }

        if (vm.getLeaseInfo() == null) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_INVALID_VM_LEASE);
        }
        StorageDomain leaseStorageDomain =
                storageDomainDao.getForStoragePool(vm.getLeaseStorageDomainId(), vm.getStoragePoolId());
        StorageDomainValidator storageDomainValidator = new StorageDomainValidator(leaseStorageDomain);
        ValidationResult validationResult = storageDomainValidator.isDomainExistAndActive();
        if (!validationResult.isValid()) {
            return new ValidationResult(EngineMessage.ACTION_TYPE_FAILED_INVALID_VM_LEASE_STORAGE_DOMAIN_STATUS,
                    String.format("$LeaseStorageDomainName %1$s", leaseStorageDomain.getName()));
        }

        return ValidationResult.VALID;
}

1.8 随机数生成器支持验证

  • 所在集群是否支持随机数生成器。
if (!checkRngDeviceClusterCompatibility()) {
        return failValidation(EngineMessage.ACTION_TYPE_FAILED_RNG_SOURCE_NOT_SUPPORTED);
}

1.9 备份存储验证

  • 正在运行的虚拟机不能包括存储在备份存储域中的磁盘。
protected ValidationResult checkDisksInBackupStorage() {
        return new MultipleStorageDomainsValidator(getVm().getStoragePoolId(),
                Stream.concat(getVm().getDiskMap()
                        .values()
                        .stream()
                        .filter(DisksFilter.ONLY_PLUGGED)
                        .filter(DisksFilter.ONLY_IMAGES)
                        .map(DiskImage.class::cast)
                        .flatMap(vmDisk -> vmDisk.getStorageIds().stream()),
                        Stream.of(getVm().getLeaseStorageDomainId()).filter(Objects::nonNull))
                .collect(Collectors.toSet()))
                .allDomainsNotBackupDomains();
}

1.10 Cloud-init 功能验证

  • CD-ROM Payload 或 Cloud-init 使用时,使用 ISE 或 sPAPR VSCSI 总线的数量有个数限制。
类型 限制数量
X86_64 3
PPC64 7
S390X 4 * 65536

1.11 CPU 类型支持验证

  • 虚拟机操作系统是否支持设置的 CPU 类型。
if (!validate(vmHandler.isCpuSupported(
                getVm().getVmOsId(),
                getVm().getCompatibilityVersion(),
                getCluster().getCpuName()))) {
            return false;
}

1.12 运行虚拟机的主机设备验证

try {
            acquireHostDevicesLock();
            if (!checkRequiredHostDevicesAvailability()) {
                return failValidation(EngineMessage.ACTION_TYPE_FAILED_HOST_DEVICE_NOT_AVAILABLE);
            }
} finally {
            releaseHostDevicesLock();
}

1.13 虚拟机 USB 设备验证

  • 未管理的 USB 控制器不能超过一个。
if (!validate(runVmValidator.validateUsbDevices(getVm().getStaticData()))) {
      return false;
}

2. 删除虚拟机

  • 删除虚拟机使用了 RemoveVmCommand 类。
  • 验证实现为 validate 方法。

2.1 虚拟机为空验证

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

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

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

2.3 删除保护限制

if (getVm().isDeleteProtected()) {
       return failValidation(EngineMessage.ACTION_TYPE_FAILED_DELETE_PROTECTION_ENABLED);
}

2.4 磁盘分离验证

  • 基于模板创建的虚拟机,不能取消 " 删除磁盘 " 选项。
  • 有创建快照的虚拟机,不能取消 " 删除磁盘 " 选项。
if (!getParameters().isRemoveDisks() && !canRemoveVmWithDetachDisks()) {
      return false;
}

2.5 虚拟机状态验证

  • 挂起的虚拟机不能删除。
  • 内部 HostedEngine 虚拟机不能删除。
  • 运行相关状态的虚拟机不能删除。
return (getVm().isHostedEngine() && isInternalExecution()) || failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_IS_RUNNING);

2.6 池虚拟机验证

  • 池中虚拟机不能删除。
if (getVm().getVmPoolId() != null) {
      return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_ATTACHED_TO_POOL);
}

2.7 虚拟机快照锁验证

if (!validate(snapshotsValidator.vmNotDuringSnapshot(getVmId()))) {
       return false;
}

2.8 数据中心中虚拟机验证

  • 运行的数据中心中运行的虚拟机不能删除。
Collection vmDisks = getVm().getDiskMap().values();
List vmImages = DisksFilter.filterImageDisks(vmDisks, ONLY_NOT_SHAREABLE, ONLY_ACTIVE);
if (!vmImages.isEmpty() && !validate(new StoragePoolValidator(getStoragePool()).existsAndUp())) {
     return false;
}

2.9 存储域验证

  • 所在存储域不是运行状态不能删除虚拟机。
  • 未强制删除且磁盘加锁的虚拟机不能删除。
vmImages.addAll(DisksFilter.filterCinderDisks(vmDisks));
        if (!vmImages.isEmpty()) {
            Set storageIds = ImagesHandler.getAllStorageIdsForImageIds(vmImages);
            MultipleStorageDomainsValidator storageValidator = new MultipleStorageDomainsValidator(getVm().getStoragePoolId(), storageIds);
            if (!validate(storageValidator.allDomainsExistAndActive())) {
                return false;
            }

            DiskImagesValidator diskImagesValidator = new DiskImagesValidator(vmImages);
            if (!getParameters().getForce() && !validate(diskImagesValidator.diskImagesNotLocked())) {
                return false;
            }
}

2.10 虚拟机租赁验证

  • 虚拟机租赁的目标存储域状态必须存在并激活。
if (getVm().getLeaseStorageDomainId() != null) {
            StorageDomain leaseStorageDomain =
                    storageDomainDao.getForStoragePool(getVm().getLeaseStorageDomainId(), getVm().getStoragePoolId());
            StorageDomainValidator storageDomainValidator = new StorageDomainValidator(leaseStorageDomain);
            if (!validate(storageDomainValidator.isDomainExistAndActive())) {
                return failValidation(EngineMessage.ACTION_TYPE_FAILED_INVALID_VM_LEASE_STORAGE_DOMAIN_STATUS,
                        String.format("$LeaseStorageDomainName %1$s", leaseStorageDomain.getName()));
            }
}

2.11 镜像锁定虚拟机验证

  • 未设置强制删除虚拟机不能删除。
  • 当有任务运行时,不能强制删除虚拟机。
VmValidator vmValidator = new VmValidator(getVm());
        ValidationResult vmLockedValidatorResult = vmValidator.vmNotLocked();
        if (!vmLockedValidatorResult.isValid()) {
            // without force remove, we can't remove the VM
            if (!getParameters().getForce()) {
                return failValidation(vmLockedValidatorResult.getMessages());
            }

            // If it is force, we cannot remove if there are task
            if (commandCoordinatorUtil.hasTasksByStoragePoolId(getVm().getStoragePoolId())) {
                return failValidation(EngineMessage.VM_CANNOT_REMOVE_HAS_RUNNING_TASKS);
            }
}

2.12 勾选 " 删除磁盘 " 选项验证

  • 需要删除的磁盘不能附加到其他的虚拟机上。
if (getParameters().isRemoveDisks() && !validate(vmValidator.vmNotHavingDeviceSnapshotsAttachedToOtherVms(false))) {
            return false;
}

3 关闭虚拟机

  • 关闭虚拟机使用了 StopVmCommandBase 类。
  • 验证实现为 validate 方法。

3.1 虚拟机状态验证

  • 虚拟机状态为关机状态直接验证通过。
if (shouldSkipCommandExecutionCached()) {
       return true;
}
  • 处于 saving/restoring 状态虚拟机不能关机。
  • 不是运行相关状态的虚拟机不能关机。
if (!getVm().isRunning() && getVm().getStatus() != VMStatus.Paused
                && getVm().getStatus() != VMStatus.NotResponding && getVm().getStatus() != VMStatus.Suspended) {
            return failValidation(
                    (getVm().getStatus().isHibernating() || getVm().getStatus() == VMStatus.RestoringState) ?
                            EngineMessage.ACTION_TYPE_FAILED_VM_IS_SAVING_RESTORING
                            : EngineMessage.ACTION_TYPE_FAILED_VM_IS_NOT_RUNNING);
}

3.2 虚拟机为空验证

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

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

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

4 暂停虚拟机

  • 暂停虚拟机使用了 PauseVmCommand 类。
  • 验证实现为 validate 方法。

4.1 虚拟机为空验证

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

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

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

4.3 虚拟机状态验证

  • 虚拟机 WaitForLaunch、MigratingFrom、NotResponding 状态不能暂停。
if (retValue && (vm.getStatus() == VMStatus.WaitForLaunch || vm.getStatus() == VMStatus.MigratingFrom || vm.getStatus() == VMStatus.NotResponding)) {
      retValue = failVmStatusIllegal();
  • 非运行状态不能暂停。
......
else if (!vm.isRunning()) {
                retValue = false;
                addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_VM_IS_NOT_RUNNING);
}

5 重启虚拟机

  • 重启虚拟机使用了 RebootVmCommand 类。
  • 验证实现为 validate 方法。

5.1 虚拟机为空验证

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

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

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

5.3 虚拟机状态验证

  • 非关机和正在关机状态不能重启。
if (getVm().getStatus() != VMStatus.Up && getVm().getStatus() != VMStatus.PoweringUp) {
      return failVmStatusIllegal();
}

6 创建虚拟机

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

6.1 相关资源对象验证

  • 群集为空验证。
if (getCluster() == null) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_CLUSTER_CAN_NOT_BE_EMPTY);
}
  • 模板为空验证。
if (getVmTemplate() == null) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_TEMPLATE_DOES_NOT_EXIST);
}
  • 模板禁用验证。
    • 创建虚拟机模板不能处于禁用状态。
if (getVmTemplate().isDisabled()) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_TEMPLATE_IS_DISABLED);
}
  • 数据中心存在验证。
StoragePoolValidator spValidator = new StoragePoolValidator(getStoragePool());
if (!validate(spValidator.exists())) {
      return false;
}
  • 创建内部虚拟机,数据中心必须处于运行状态。
if (!isExternalVM() && !validate(spValidator.isInStatus(StoragePoolStatus.Up))) {
      return false;
}
  • 虚拟机模板必须属于当前所在数据中心。
if (!isTemplateInValidDc()) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_TEMPLATE_NOT_EXISTS_IN_CURRENT_DC);
}
  • 虚拟机名称为空验证。
if (StringUtils.isEmpty(vmFromParams.getName())) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_NAME_MAY_NOT_BE_EMPTY);
}
  • 虚拟机名称长度验证。
    • MaxVmNameLength 定义了虚拟机名称最大长度(默认为 64)
if (!isVmNameValidLength(vmFromParams)) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_NAME_LENGTH_IS_TOO_LONG);
}

6.2 磁盘格式验证

  • Thin provisioned 模板磁盘不能被定义为 Raw。
protected boolean isDisksVolumeFormatValid() {
        if (diskInfoDestinationMap.values().stream()
                .anyMatch(d -> d.getDiskStorageType() != DiskStorageType.CINDER &&
                        d.getVolumeFormat() != VolumeFormat.COW)) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_THIN_TEMPLATE_DISKS_SHOULD_ONLY_BE_COW);
        }
        return true;
}

6.3 自定义兼容版本支持验证

  • 支持群集版本。
Version customCompatibilityVersionFromParams = getParameters().getVmStaticData().getCustomCompatibilityVersion();
        if (customCompatibilityVersionFromParams != null && !isCompatibilityVersionSupportedByCluster(customCompatibilityVersionFromParams)) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_CUSTOM_COMPATIBILITY_VERSION_NOT_SUPPORTED,
        String.format("$Ccv %s", customCompatibilityVersionFromParams));
}

6.4 群集架构支持验证

  • 群集不具有定义的架构。
if (getCluster().getArchitecture() == ArchitectureType.undefined) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_CLUSTER_UNDEFINED_ARCHITECTURE);
}
  • 所选的模板和集群架构不兼容。
if (!getVmTemplate().getId().equals(VmTemplateHandler.BLANK_VM_TEMPLATE_ID) && getCluster().getArchitecture() != getVmTemplate().getClusterArch()) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_TEMPLATE_IS_INCOMPATIBLE);
}
  • 群集架构支持内存气球验证
if (isBalloonEnabled() && !osRepository.isBalloonEnabled(getParameters().getVmStaticData().getOsId(),
                getEffectiveCompatibilityVersion())) {
            addValidationMessageVariable("clusterArch", getCluster().getArchitecture());
            return failValidation(EngineMessage.BALLOON_REQUESTED_ON_NOT_SUPPORTED_ARCH);
}
  • 群集架构支持音频设备验证
if (isSoundDeviceEnabled() && !osRepository.isSoundDeviceEnabled(getParameters().getVmStaticData().getOsId(),
                getEffectiveCompatibilityVersion())) {
            addValidationMessageVariable("clusterArch", getCluster().getArchitecture());
            return failValidation(EngineMessage.SOUND_DEVICE_REQUESTED_ON_NOT_SUPPORTED_ARCH);
}
  • 群集架构支持操作系统验证
if (!validate(vmHandler.isOsTypeSupported(vmFromParams.getOs(), getCluster().getArchitecture()))) {
            return false;
}
  • 群集架构支持迁移验证
if (!FeatureSupported.isMigrationSupported(getCluster().getArchitecture(), getEffectiveCompatibilityVersion())
                && vmFromParams.getMigrationSupport() != MigrationSupport.PINNED_TO_HOST) {
            return failValidation(EngineMessage.VM_MIGRATION_IS_NOT_SUPPORTED);
}

6.5 兼容版本支持高性能虚拟机验证

if (getParameters().getVmStaticData().getVmType() == VmType.HighPerformance
                && !FeatureSupported.isHighPerformanceTypeSupported(getEffectiveCompatibilityVersion())) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_HIGH_PERFORMANCE_IS_NOT_SUPPORTED,
           String.format("$Version %s", getEffectiveCompatibilityVersion()));
}

6.6 配额验证

if (!validateQuota(getParameters().getVmStaticData().getQuotaId())) {
      return false;
}

6.7 CPU Pinning 验证

  • 可迁移的虚拟机不能固定到 CPU。
boolean validatePinningAndMigration() {
        final boolean cpuPinMigrationEnabled = Boolean.TRUE.equals(Config. getValue(ConfigValues.CpuPinMigrationEnabled));
        VmStatic vmStaticData = getParameters().getVmStaticData();
        if (!cpuPinMigrationEnabled
                && (vmStaticData.getMigrationSupport() == MigrationSupport.MIGRATABLE
                || vmStaticData.getMigrationSupport() == MigrationSupport.IMPLICITLY_NON_MIGRATABLE)
                && StringUtils.isNotEmpty(getParameters().getVm().getCpuPinning())) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_CANNOT_BE_PINNED_TO_CPU_AND_MIGRATABLE);
        }
        return true;
}
  • 带有主机 CPU 标记的虚拟机必须被固定到主机上。
if (vmFromParams.isUseHostCpuFlags()
                && vmFromParams.getMigrationSupport() != MigrationSupport.PINNED_TO_HOST) {
            return failValidation(EngineMessage.VM_HOSTCPU_MUST_BE_PINNED_TO_HOST);
}
  • CPU 固定格式无效。
  • 未选择主机时无法设置主机 CPU 固定。
  • CPU 固定检验失败 - 虚拟机里不存在虚拟 CPU。
  • 无法在相同的 vCPU 上配置两次 CPU 固定。
  • 无法将 vCPU 固定到非 pCPU 上。
if (!validate(isCpuPinningValid(vmFromParams.getCpuPinning(), vmFromParams.getStaticData()))) {
            return false;
}
  • 带有主机 CPU 标记的虚拟机必须被固定到主机上。
if (vmFromParams.isUseHostCpuFlags()
                && vmFromParams.getMigrationSupport() != MigrationSupport.PINNED_TO_HOST) {
            return failValidation(EngineMessage.VM_HOSTCPU_MUST_BE_PINNED_TO_HOST);
}
  • 架构不支持主机 CPU 透传。
if (vmFromParams.isUseHostCpuFlags() && (ArchitectureType.ppc == getCluster().getArchitecture().getFamily())) {
            return failValidation(EngineMessage.USE_HOST_CPU_REQUESTED_ON_UNSUPPORTED_ARCH);
}

6.8 监控器数量验证

图像类型 支持数量
VNC <=1
SPICE <=ValidNumOfMonitors(默认值为 4)
protected boolean checkNumberOfMonitors() {
        if (getParameters().getVmStaticData().getDefaultDisplayType() == DisplayType.none) {
            return true;
        }
        Collection graphicsTypes = vmHandler.getResultingVmGraphics(
                getVmDeviceUtils().getGraphicsTypesOfEntity(getVmTemplateId()),
                getParameters().getGraphicsDevices());
        int numOfMonitors = getParameters().getVmStaticData().getNumOfMonitors();
        return validate(vmHandler.isNumOfMonitorsLegal(graphicsTypes, numOfMonitors));
}

6.9 显示设备验证

  • 不能通过 VNC 设置单个显示设备。
  • 不能在非 Linux 操作系统上设置单个显示设备。
protected boolean checkSingleQxlDisplay() {
        if (!getParameters().getVmStaticData().getSingleQxlPci() || getParameters().getVmStaticData().getDefaultDisplayType() == DisplayType.none) {
            return true;
        }
        return validate(vmHandler.isSingleQxlDeviceLegal(getParameters().getVm().getDefaultDisplayType(), getParameters().getVm().getOs()));
}

6.10 PCI 和 IDE 数量支持验证

validate(VmValidator.checkPciAndIdeLimit(getParameters().getVm().getOs(),
                        getEffectiveCompatibilityVersion(),
                        getParameters().getVmStaticData().getNumOfMonitors(),
                        getVmInterfaces(),
                        getDiskVmElements(),
                        isVirtioScsiEnabled(),
                        hasWatchdog(),
                        isBalloonEnabled(),
                        isSoundDeviceEnabled()))

6.11 虚拟机名称重复验证

if (isVmWithSameNameExists(name, storagePoolId)) {
      return failValidation(EngineMessage.ACTION_TYPE_FAILED_NAME_ALREADY_USED);
}

6.12 Mac 池地址范围验证

if (!validate(vmHandler.verifyMacPool(getVmInterfaces().size(), getMacPool()))) {
     return false;
}

6.13 虚拟机优先级值范围验证

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

6.14 虚拟机模板使用验证

protected boolean checkTemplateImages() {
        if (getParameters().getParentCommand() == ActionType.AddVmPool) {
            return true;
        }

        for (StorageDomain storage : destStorages.values()) {
            if (!validate(vmTemplateHandler.isVmTemplateImagesReady(vmDisksSource, storage.getId(),
                    false, false, true, true,
                    storageToDisksMap.get(storage.getId())))) {
                return false;
            }
        }
        return true;
}

6.15 自定义属性验证

if (!validateCustomProperties(vmStaticFromParams)) {
      return false;
}

6.16 存储域验证

  • 存储域必须所属同样的数据中心。
  • 数据中心至少有一个可用的存储域。
  • 存储域使用空间验证。
if (!getStoragePoolId().equals(getStoragePoolIdFromSourceImageContainer())) {
                return failValidation(EngineMessage.ACTION_TYPE_FAILED_STORAGE_POOL_NOT_MATCH);
}
for (StorageDomain domain : destStorages) {
               StorageDomainValidator storageDomainValidator = new StorageDomainValidator(domain);
               if (!validate(storageDomainValidator.isDomainExistAndActive())) {
                   return false;
               }
}
......
protected boolean validateFreeSpace(StorageDomainValidator storageDomainValidator, List disksList) {
        Collection disks = ImagesHandler.getDisksDummiesForStorageAllocations(disksList);
        return validate(storageDomainValidator.hasSpaceForNewDisks(disks));
}

6.17 虚拟机 Payload 验证

  • 支持 Payload 的类型只有 CDROM 和 FLOPPY。
  • Payload 最大限制为 PayloadSize(默认值为 8192)
if (getParameters().getVmPayload() != null) {
            if (!checkPayload(getParameters().getVmPayload())) {
                return false;
            }

            // otherwise, we save the content in base64 string
            for (Map.Entry entry : getParameters().getVmPayload().getFiles().entrySet()) {
                entry.setValue(new String(BASE_64.encode(entry.getValue().getBytes()), StandardCharsets.UTF_8));
            }
}

6.18 虚拟机看门狗兼容性验证

if (getParameters().getWatchdog() != null) {
            if (!validate(new VmWatchdogValidator(vmFromParams.getOs(),
                    getParameters().getWatchdog(),
                    getEffectiveCompatibilityVersion()).isValid())) {
                return false;
            }
}

6.19 虚拟机 CPU 架构支持验证

public ValidationResult isCpuSupported(int osId, Version version, String cpuName) {
        String cpuId = cpuFlagsManagerHandler.getCpuId(cpuName, version);
        if (cpuId == null) {
            return new ValidationResult(EngineMessage.CPU_TYPE_UNKNOWN);
        }
        if (!osRepository.isCpuSupported(
                osId,
                version,
                cpuId)) {
            String unsupportedCpus = osRepository.getUnsupportedCpus(osId, version).toString();
            return new ValidationResult(EngineMessage.CPU_TYPE_UNSUPPORTED_FOR_THE_GUEST_OS,
                    "$unsupportedCpus " + StringUtils.strip(unsupportedCpus, "[]"));
        }
        return ValidationResult.VALID;
}

6.20 虚拟机图形显示支持验证

if (!validate(vmHandler.isGraphicsAndDisplaySupported(getParameters().getVmStaticData().getOsId(),
                vmHandler.getResultingVmGraphics(
                        getVmDeviceUtils().getGraphicsTypesOfEntity(getVmTemplateId()),
                        getParameters().getGraphicsDevices()),
                vmFromParams.getDefaultDisplayType(),
                getEffectiveCompatibilityVersion()))) {
            return false;
}

6.21 虚拟机智能卡支持验证

  • 高性能虚拟机类型禁用 USB 时,不支持启用智能卡设备。
if (!validate(vmHandler.validateSmartCardDevice(getParameters().getVmStaticData()))) {
      return false;
}

6.22 内存验证

  • ppc 系统架构上,内存的大小需要是 256 的倍数。
if (!validateMemoryAlignment(getParameters().getVmStaticData())) {
       return false;
}

6.23 实例类型为空验证

if (getInstanceTypeId() != null && getInstanceType() == null) {
            // invalid instance type
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_INSTANCE_TYPE_DOES_NOT_EXIST);
}

6.24 镜像类型为空验证

if (imageTypeId != null && getImageType() == null) {
            // invalid image type
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_IMAGE_TYPE_DOES_NOT_EXIST);
}

6.25 CPU 数量验证

if (!validate(VmValidator.validateCpuSockets(getParameters().getVmStaticData(), getEffectiveCompatibilityVersion()))) {
      return false;
}

6.26 CPU 共享验证

  • 范围值必须是 0 到 262144 之间。
if (!isCpuSharesValid(vmFromParams)) {
            return failValidation(EngineMessage.QOS_CPU_SHARES_OUT_OF_RANGE);
}

6.27 CPU 内核线程验证

if (!VmCpuCountHelper.validateCpuCounts(vmFromParams)) {
        return failValidation(EngineMessage.TOO_MANY_CPU_COMPONENTS);
}

6.28 系统 VirtIO-SCSI 支持验证

public ValidationResult isOsTypeSupportedForVirtioScsi(int osId, Version clusterVersion) {
        return ValidationResult
                .failWith(EngineMessage.ACTION_TYPE_FAILED_ILLEGAL_OS_TYPE_DOES_NOT_SUPPORT_VIRTIO_SCSI)
                .unless(vmValidationUtils.isDiskInterfaceSupportedByOs(osId, clusterVersion, DiskInterface.VirtIO_SCSI));
}

6.29 虚拟机物理内存验证

  • 虚拟机物理内存不能超过内存总量。
if (vmFromParams.getMinAllocatedMem() > vmFromParams.getMemSizeMb()) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_MIN_MEMORY_CANNOT_EXCEED_MEMORY_SIZE);
}

6.30 磁盘配置集验证

  • 用户没有权限为磁盘附加磁盘配置集。
  • 必须有一个在存储域中定义的配置集。
private boolean setAndValidateDiskProfiles() {
        if (diskInfoDestinationMap != null && !diskInfoDestinationMap.isEmpty()) {
            Map map = new HashMap<>();
            List diskImages = DisksFilter.filterImageDisks(diskInfoDestinationMap.values(),
                    ONLY_NOT_SHAREABLE,
                    ONLY_ACTIVE);
            for (DiskImage diskImage : diskImages) {
                map.put(diskImage, diskImage.getStorageIds().get(0));
            }
            return validate(diskProfileHelper.setAndValidateDiskProfiles(map, getCurrentUser()));
        }
        return true;
}

6.31 CPU 配置集验证

  • 指定 ID 的 CPU 配置集不存在。
  • CPU 配置集与集群不匹配。
  • 用户没有权限把指定 ID 的配置集分配给 VM。
protected boolean setAndValidateCpuProfile() {
        return validate(cpuProfileHelper.setAndValidateCpuProfile(
                getParameters().getVm().getStaticData(),
                getUserIdIfExternal().orElse(null)));
}

6.32 Cinder 磁盘验证

List cinderDisks = DisksFilter.filterCinderDisks(diskInfoDestinationMap.values());
        CinderDisksValidator cinderDisksValidator = new CinderDisksValidator(cinderDisks);
if (!validate(cinderDisksValidator.validateCinderDiskLimits())) {
            return false;
}

6.33 虚拟机图标验证

  • 自定义图标验证
if (getParameters().getVmLargeIcon() != null && !validate(IconValidator.validate(
                IconValidator.DimensionsType.LARGE_CUSTOM_ICON,
                getParameters().getVmLargeIcon()))) {
            return false;
}
  • 小图标验证
if (getSmallIconId() != null
                && getParameters().getVmLargeIcon() == null // icon id is ignored if large icon is sent
                && !validate(IconValidator.validateIconId(getSmallIconId(), "Small"))) {
            return false;
}
  • 大图标验证
if (getLargeIconId() != null
                && getParameters().getVmLargeIcon() == null // icon id is ignored if large icon is sent
                && !validate(IconValidator.validateIconId(getLargeIconId(), "Large"))) {
            return false;
}

6.34 numa 节点验证

if (!validate(getNumaValidator().checkVmNumaNodesIntegrity(
                getParameters().getVm(),
                getParameters().getVm().getvNumaNodeList()))) {
            return false;
}

6.35 群集升级模式验证

if (getCluster().isInUpgradeMode()) {
            getParameters().getVm().setClusterCompatibilityVersion(getCluster().getCompatibilityVersion());
            if (!validate(getClusterUpgradeValidator().isVmReadyForUpgrade(getParameters().getVm()))) {
                return false;
            }
}

6.36 虚拟机最大内存验证

  • 内存大小不能超过最大内存。
  • 最大内存不能超过平台的限制。
if (!validate(vmHandler.validateMaxMemorySize(
                getParameters().getVmStaticData(),
                getEffectiveCompatibilityVersion()))) {
            return false;
}

6.37 虚拟机租赁验证

  • 虚拟机兼容性版本是否支持虚拟机租赁。
  • 一个虚拟机租赁已被定义,但高可用性被设置为 false。
if (shouldAddLease(getParameters().getVmStaticData()) && !canAddLease()) {
            return false;
}

6.38 虚拟机 cloud-init 验证

  • cloud-init 配置中的 Start On Boot 选择无效。只支持 " true "。
  • cloud-init 配置中需要静态 IPv4 地址。
  • cloud-init 配置中需要静态 IPv6 地址。
  • cloud-init 配置中的选项 'autoconf' 不被支持。
List msgs = openStackMetadataAdapter.validate(getParameters().getVmStaticData().getVmInit());
if (!CollectionUtils.isEmpty(msgs)) {
       return failValidation(msgs);
}

7 添加磁盘

  • 添加磁盘使用了 AddDiskCommand 类。
  • 验证实现为 validate 方法。

7.1 磁盘数据验证

protected boolean validateDiskVmData() {
        if (getDiskVmElement() == null || getDiskVmElement().getId() == null ||
                !Objects.equals(getDiskVmElement().getId().getVmId(), getVmId())) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_DISK_VM_DATA_MISSING);
        }
        return true;
}

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

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

7.3 引导磁盘验证

  • 虚拟机只能包含一个引导磁盘。
if (getDiskVmElement().isBoot() && !validate(diskValidator.isVmNotContainsBootDisk(vm))) {
                return false;
}

7.4 磁盘擦除支持验证

  • PassDiscardSupported 版本支持情况。
if (!validatePassDiscardSupported(diskVmElementValidator)) {
     return false;
}

7.5 PCI 和 IDE 数量支持验证

VmValidator.checkPciAndIdeLimit(getVm().getOs(),
                getVm().getCompatibilityVersion(),
                getVm().getNumOfMonitors(),
                vmInterfaces,
                diskVmElements,
                isVirtioScsiControllerAttached(getVmId()),
                hasWatchdog(getVmId()),
                isBalloonEnabled(getVmId()),
                isSoundDeviceEnabled(getVmId()))
......

7.6 只读磁盘验证

  • IDE 磁盘不能是只读的。
  • 只读磁盘不支持 SCSI 设备透传。
if (!validate(diskVmElementValidator.isReadOnlyPropertyCompatibleWithInterface())) {
     return false;
}

7.7 配额验证

protected boolean validateQuota() {
        if (!getParameters().getDiskInfo().getDiskStorageType().isInternal()) {
            return true;
        }

        return validateQuota(((DiskImage) getParameters().getDiskInfo()).getQuotaId());
}

7.8 磁盘配置集验证

  • 与 6.30 一致。

7.9 Lun 类型磁盘验证

  • Lun 连接对象验证。
    • 提供的 lun 没有有效的 lun 类型。
    • 提供的 LUN 丢缺失了至少一个连接参数(address/port/iqn)。
if (!validate(diskValidator.validateConnectionsInLun(lun.getLunType()))) {
            return false;
}
  • 是否已使用验证。
if (!validate(diskValidator.validateLunAlreadyInUse())) {
            return false;
}
  • 虚拟机锁验证。
getVm()).vmNotLocked()
  • 快照相关验证。
    • 快照锁验证。
    • 快照不能处于预览状态。
isVmNotInPreviewSnapshot()
  • 虚拟机必须启用 VirtIO-SCSI。
if (!validate(diskVmElementValidator.isVirtIoScsiValid(getVm()))) {
       return false;
}
  • 磁盘接口是否被操作系统支持。
if (!validate(diskVmElementValidator.isDiskInterfaceSupported(getVm()))) {
       return false;
}
  • 存储服务器是否连接验证
if (getVds() != null) {
            lunFromStorage = getLunDisk(lun, getVds());
            if (lunFromStorage == null) {
                return failValidation(EngineMessage.ACTION_TYPE_FAILED_DISK_LUN_INVALID);
            }
}
  • SCSI 预留验证
    • SCSI 预留只能在 SGIO 没有被过滤的情况下设置。
if (!validate(diskValidator.isUsingScsiReservationValid(getVm(), getDiskVmElement(), lunDisk))) {
            return false;
}

7.10 存储域验证

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

7.11 Cinder 磁盘验证

  • 超过了允许的最大卷数量不能在存储域中创建 Cinder 磁盘。
cinderDisksValidator.validateCinderDiskLimits()

7.12 Cinder 卷验证

  • Cinder 卷类型不存在。
cinderDisksValidator.validateCinderVolumeTypesExist()

8 删除磁盘

  • 删除磁盘使用了 RemoveDiskCommand 类。
  • 验证实现为 validate 方法。

8.1 磁盘为空验证

if (getDisk() == null) {
            return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_IMAGE_DOES_NOT_EXIST);
}

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

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

8.3 挂载磁盘虚拟机验证

  • 挂载该磁盘的虚拟机必须都关机。
private boolean validateAllVmsForDiskAreDown() {
        if (getDisk().getVmEntityType() != null && getDisk().getVmEntityType().isVmType()) {
            for (VM vm : getVmsForDiskId()) {
                if (vm.getStatus() != VMStatus.Down && !vm.isHostedEngine()) {
                    VmDevice vmDevice = vmDeviceDao.get(new VmDeviceId(getDisk().getId(), vm.getId()));
                    if (vmDevice.isPlugged()) {
                        addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_VM_IS_NOT_DOWN);
                        return false;
                    }
                }
            }
        }

        return true;
}

8.4 存储域验证

  • 删除一个模板的磁盘副本时,必须指定存储域。
  • 提供的存储域错误,它和磁盘没有关联。
canRemoveDiskBasedOnImageStorageCheck()

9 激活磁盘

  • 激活磁盘使用了 HotPlugDiskToVmCommand 类。
  • 验证实现为 validate 方法。

9.1 虚拟机验证

  • 虚拟机必须存在。
VmValidator(getVm()).isVmExists())
  • 虚拟机状态验证
    • 虚拟机必须为 Up、Down 或者 Paused 状态。
protected boolean isVmInUpPausedDownStatus() {
        if (getVm().getStatus() != VMStatus.Up && getVm().getStatus() != VMStatus.Down
                && getVm().getStatus() != VMStatus.Paused) {
            return failVmStatusIllegal();
        }
        return true;
}

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

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

9.3 磁盘附加验证

protected boolean isDiskExistAndAttachedToVm(Disk disk) {
        DiskValidator diskValidator = getDiskValidator(disk);
        return validate(diskValidator.isDiskExists()) && validate(diskValidator.isDiskAttachedToVm(getVm()));
}

9.4 磁盘接口支持验证

private boolean interfaceDiskValidation() {
        DiskVmElementValidator diskVmElementValidator = getDiskVmElementValidator(disk, getDiskVmElement());
        return validate(diskVmElementValidator.isDiskInterfaceSupported(getVm()));
}

9.5 磁盘已激活验证

  • 该磁盘不能处于已激活状态。
if (getPlugAction() == VDSCommandType.HotPlugDisk && oldVmDevice.isPlugged()) {
            return failValidation(EngineMessage.HOT_PLUG_DISK_IS_NOT_UNPLUGGED);
}

9.6 快照验证

  • 快照锁验证。
  • 快照不能处于预览状态。
protected boolean isVmNotInPreviewSnapshot() {
        return
                getVmId() != null &&
                validate(snapshotsValidator.vmNotDuringSnapshot(getVmId())) &&
                validate(snapshotsValidator.vmNotInPreview(getVmId()));
}

9.7 存储域验证

  • 至少有一个激活的存储域。
storageDomainValidator.isDomainExistAndActive()
  • 正在运行的虚拟机不能包括存储在备份存储域中的磁盘。
storageDomainValidator.isNotBackupDomain()

9.8 VirtIO-SCSI 启用验证

private boolean virtIoScsiDiskValidation() {
        DiskVmElementValidator diskVmElementValidator = getDiskVmElementValidator(disk, getDiskVmElement());
        return validate(diskVmElementValidator.isVirtIoScsiValid(getVm()));
}

9.9 磁盘擦除支持验证

  • 与 7.4 一致。

10 取消激活磁盘

  • 与激活磁盘的验证流程一致。
    • 9.6 更改为磁盘已未取消激活验证。
      • 该磁盘不能处于取消激活状态
if (getPlugAction() == VDSCommandType.HotUnPlugDisk && !oldVmDevice.isPlugged()) {
            return failValidation(EngineMessage.HOT_UNPLUG_DISK_IS_NOT_PLUGGED);
}

你可能感兴趣的:(【Ovirt 笔记】虚拟机相关业务验证分析与整理(1))