文前说明
作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。
本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。
分析整理的版本为 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 配置验证一致。
网友评论