package org.ovirt.engine.core.bll.memory;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.ovirt.engine.core.bll.utils.VmOverheadCalculator;
import org.ovirt.engine.core.common.businessentities.Snapshot;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.businessentities.storage.DiskContentType;
import org.ovirt.engine.core.common.businessentities.storage.DiskImage;
import org.ovirt.engine.core.common.businessentities.storage.StorageType;
import org.ovirt.engine.core.common.businessentities.storage.VolumeFormat;
import org.ovirt.engine.core.common.businessentities.storage.VolumeType;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.utils.GuidUtils;
public class MemoryUtils {
/** The size for the snapshot's meta data which is vm related properties at the
* time the snapshot was taken */
public static final long METADATA_SIZE_IN_BYTES = 10 * 1024;
private static final String VM_HIBERNATION_METADATA_DISK_DESCRIPTION = "metadata for VM hibernation";
private static final String VM_HIBERNATION_MEMORY_DISK_DESCRIPTION = "memory dump for VM hibernation";
private static final String VM_HIBERNATION_METADATA_DISK_ALIAS_PATTERN = "%s_hibernation_metadata";
private static final String VM_HIBERNATION_MEMORY_DISK_ALIAS_PATTERN = "%s_hibernation_memory";
private static final String VM_SNAPSHOT_METADATA_DISK_DESCRIPTION = "metadata for VM snapshot";
private static final String VM_SNAPSHOT_MEMORY_DISK_DESCRIPTION = "memory dump for VM snapshot";
private static final String VM_SNAPSHOT_METADATA_DISK_ALIAS = "snapshot_metadata";
private static final String VM_SNAPSHOT_MEMORY_DISK_ALIAS = "snapshot_memory";
/**
* Modified the given memory volume String representation to have the given storage
* pool and storage domain
*/
public static String changeStorageDomainAndPoolInMemoryState(
String originalMemoryVolume, Guid storageDomainId, Guid storagePoolId) {
List<Guid> guids = GuidUtils.getGuidListFromString(originalMemoryVolume);
return createMemoryStateString(storageDomainId, storagePoolId,
guids.get(2), guids.get(3), guids.get(4), guids.get(5));
}
public static String createMemoryStateString(
Guid storageDomainId, Guid storagePoolId, Guid memoryImageId,
Guid memoryVolumeId, Guid confImageId, Guid confVolumeId) {
return String.format("%1$s,%2$s,%3$s,%4$s,%5$s,%6$s",
storageDomainId,
storagePoolId,
memoryImageId,
memoryVolumeId,
confImageId,
confVolumeId);
}
public static Set<String> getMemoryVolumesFromSnapshots(List<Snapshot> snapshots) {
Set<String> memories = new HashSet<>();
for (Snapshot snapshot : snapshots) {
memories.add(snapshot.getMemoryVolume());
}
memories.remove(StringUtils.EMPTY);
return memories;
}
public static List<DiskImage> createDiskDummies(long memorySize, long metadataSize) {
DiskImage memoryVolume = new DiskImage();
memoryVolume.setDiskAlias("memory");
memoryVolume.setVolumeFormat(VolumeFormat.RAW);
memoryVolume.setSize(memorySize);
memoryVolume.setActualSizeInBytes(memorySize);
memoryVolume.getSnapshots().add(memoryVolume);
DiskImage dataVolume = new DiskImage();
dataVolume.setDiskAlias("metadata");
dataVolume.setVolumeFormat(VolumeFormat.RAW);
dataVolume.setVolumeType(VolumeType.Preallocated);
dataVolume.setSize(metadataSize);
dataVolume.setActualSizeInBytes(metadataSize);
dataVolume.getSnapshots().add(dataVolume);
return Arrays.asList(memoryVolume, dataVolume);
}
public static DiskImage createSnapshotMetadataDisk() {
DiskImage image = createMetadataDisk();
image.setDiskAlias(VM_SNAPSHOT_METADATA_DISK_ALIAS);
image.setDescription(VM_SNAPSHOT_METADATA_DISK_DESCRIPTION);
return image;
}
public static DiskImage createHibernationMetadataDisk(VM vm) {
DiskImage image = createMetadataDisk();
image.setDiskAlias(generateHibernationMetadataDiskAlias(vm.getName()));
image.setDescription(VM_HIBERNATION_METADATA_DISK_DESCRIPTION);
return image;
}
public static DiskImage createMetadataDisk() {
DiskImage image = new DiskImage();
image.setSize(MemoryUtils.METADATA_SIZE_IN_BYTES);
image.setVolumeType(VolumeType.Preallocated);
image.setVolumeFormat(VolumeFormat.RAW);
image.setContentType(DiskContentType.MEMORY_METADATA_VOLUME);
return image;
}
private static String generateHibernationMetadataDiskAlias(String vmName) {
return String.format(VM_HIBERNATION_METADATA_DISK_ALIAS_PATTERN, vmName);
}
public static DiskImage createSnapshotMemoryDisk(VM vm, StorageType storageType, VmOverheadCalculator vmOverheadCalculator) {
DiskImage image = createMemoryDisk(vm, storageType, vmOverheadCalculator);
image.setDiskAlias(VM_SNAPSHOT_MEMORY_DISK_ALIAS);
image.setDescription(VM_SNAPSHOT_MEMORY_DISK_DESCRIPTION);
return image;
}
public static DiskImage createHibernationMemoryDisk(VM vm, StorageType storageType, VmOverheadCalculator vmOverheadCalculator) {
DiskImage image = createMemoryDisk(vm, storageType, vmOverheadCalculator);
image.setDiskAlias(generateHibernationMemoryDiskAlias(vm.getName()));
image.setDescription(VM_HIBERNATION_MEMORY_DISK_DESCRIPTION);
return image;
}
public static DiskImage createMemoryDisk(VM vm, StorageType storageType, VmOverheadCalculator vmOverheadCalculator) {
DiskImage image = new DiskImage();
image.setSize(vmOverheadCalculator.getSnapshotMemorySizeInBytes(vm));
image.setVolumeType(storageTypeToMemoryVolumeType(storageType));
image.setVolumeFormat(VolumeFormat.RAW);
image.setContentType(DiskContentType.MEMORY_DUMP_VOLUME);
return image;
}
private static String generateHibernationMemoryDiskAlias(String vmName) {
return String.format(VM_HIBERNATION_MEMORY_DISK_ALIAS_PATTERN, vmName);
}
/**
* Returns whether to use Sparse or Preallocation. If the storage type is file system devices ,it would be more
* efficient to use Sparse allocation. Otherwise for block devices we should use Preallocated for faster allocation.
*
* @return - VolumeType of allocation type to use.
*/
public static VolumeType storageTypeToMemoryVolumeType(StorageType storageType) {
return storageType.isFileDomain() ? VolumeType.Sparse : VolumeType.Preallocated;
}
public static Guid getMemoryDiskId(String memoryVolume) {
return StringUtils.isEmpty(memoryVolume) ? null
: GuidUtils.getGuidListFromString(memoryVolume).get(2);
}
public static Guid getMetadataDiskId(String memoryVolume) {
return StringUtils.isEmpty(memoryVolume) ? null
: GuidUtils.getGuidListFromString(memoryVolume).get(4);
}
}