package org.ovirt.engine.core.common.businessentities.storage;
import java.util.ArrayList;
import java.util.Date;
import java.util.Objects;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.ovirt.engine.core.common.businessentities.VmEntityType;
import org.ovirt.engine.core.common.utils.ObjectUtils;
import org.ovirt.engine.core.common.utils.SizeConverter;
import org.ovirt.engine.core.compat.Guid;
public class DiskImage extends DiskImageBase {
private static final long serialVersionUID = 3185087852755356847L;
private Date lastModifiedDate;
private ArrayList<String> storagesNames;
private long actualSizeInBytes;
private int readRateFromDiskImageDynamic;
private int writeRateFromDiskImageDynamic;
// Latency fields from DiskImageDynamic which are measured in seconds.
private Double readLatency;
private Double writeLatency;
private Double flushLatency;
private String appList;
// TODO from storage_domain_static
private Guid storagePoolId;
private ArrayList<DiskImage> snapshots;
private double actualDiskWithSnapthotsSize;
private ArrayList<Guid> quotaIds;
private ArrayList<String> quotaNames;
private ArrayList<Guid> diskProfileIds;
private ArrayList<String> diskProfileNames;
private String vmSnapshotDescription;
public DiskImage() {
setParentId(Guid.Empty);
setCreationDate(new Date());
setLastModifiedDate(getCreationDate());
snapshots = new ArrayList<>();
}
public Guid getImageId() {
return getImage().getId();
}
public void setImageId(Guid id) {
getImage().setId(id);
}
private VmEntityType vmEntityType;
@Override
public VmEntityType getVmEntityType() {
return vmEntityType;
}
@Override
public void setVmEntityType(VmEntityType vmEntityType) {
this.vmEntityType = vmEntityType;
}
public Boolean getActive() {
return getImage().isActive();
}
@Override
@JsonIgnore
public boolean isDiskSnapshot() {
return !getActive();
}
public void setDiskSnapshot(boolean diskSnapshot) {
setActive(!diskSnapshot);
}
@JsonIgnore
public Guid getSnapshotId() {
return isDiskSnapshot() ? getVmSnapshotId() : null;
}
public void setActive(boolean active) {
getImage().setActive(active);
}
public VolumeClassification getVolumeClassification() {
return getImage().getVolumeClassification();
}
public void setVolumeClassification(VolumeClassification volumeClassification) {
getImage().setVolumeClassification(volumeClassification);
}
public Date getCreationDate() {
return getImage().getCreationDate();
}
public void setCreationDate(Date creationDate) {
getImage().setCreationDate(creationDate);
}
public Date getLastModifiedDate() {
return lastModifiedDate;
}
public void setLastModifiedDate(Date lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
public long getActualSizeInBytes() {
return actualSizeInBytes;
}
public void setActualSizeInBytes(long size) {
actualSizeInBytes = size;
setActualSize(getActualSizeInBytes() * 1.0 / (1024 * 1024 * 1024));
}
public boolean hasActualSize() {
return true;
}
public int getReadRate() {
return readRateFromDiskImageDynamic;
}
public void setReadRate(int readRateFromDiskImageDynamic) {
this.readRateFromDiskImageDynamic = readRateFromDiskImageDynamic;
}
public int getWriteRate() {
return writeRateFromDiskImageDynamic;
}
public void setWriteRate(int writeRateFromDiskImageDynamic) {
this.writeRateFromDiskImageDynamic = writeRateFromDiskImageDynamic;
}
public Double getReadLatency() {
return readLatency;
}
public void setReadLatency(Double readLatency) {
this.readLatency = readLatency;
}
public Double getWriteLatency() {
return writeLatency;
}
public void setWriteLatency(Double writeLatency) {
this.writeLatency = writeLatency;
}
public Double getFlushLatency() {
return flushLatency;
}
public void setFlushLatency(Double flushLatency) {
this.flushLatency = flushLatency;
}
private String description;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getAppList() {
return appList;
}
public void setAppList(String appList) {
this.appList = appList;
}
public Guid getImageTemplateId() {
return getImage().getTemplateImageId();
}
public void setImageTemplateId(Guid guid) {
getImage().setTemplateImageId(guid);
}
public Guid getParentId() {
return getImage().getParentId();
}
public void setParentId(Guid parentId) {
getImage().setParentId(parentId);
}
public ImageStatus getImageStatus() {
return getImage().getStatus();
}
public void setImageStatus(ImageStatus imageStatus) {
getImage().setStatus(imageStatus);
}
public Date getLastModified() {
return getImage().getLastModified();
}
public void setLastModified(Date lastModified) {
getImage().setLastModified(lastModified);
}
private ArrayList<Guid> storageIds;
private ArrayList<StorageType> storageTypes;
public ArrayList<Guid> getStorageIds() {
return storageIds;
}
public void setStorageIds(ArrayList<Guid> storageIds) {
this.storageIds = storageIds;
}
public ArrayList<StorageType> getStorageTypes() {
return storageTypes;
}
public void setStorageTypes(ArrayList<StorageType> storageTypes) {
this.storageTypes = storageTypes;
}
public Guid getVmSnapshotId() {
return getImage().getSnapshotId();
}
public void setVmSnapshotId(Guid snapshotId) {
getImage().setSnapshotId(snapshotId);
}
public String getVmSnapshotDescription() {
return vmSnapshotDescription;
}
public void setVmSnapshotDescription(String vmSnapshotDescription) {
this.vmSnapshotDescription = vmSnapshotDescription;
}
public ArrayList<String> getStoragesNames() {
return storagesNames;
}
public void setStoragesNames(ArrayList<String> storagesNames) {
this.storagesNames = storagesNames;
}
public Guid getStoragePoolId() {
return storagePoolId;
}
public void setStoragePoolId(Guid storagePoolId) {
this.storagePoolId = storagePoolId;
}
private double actualSize;
/**
* Get the actual Size of the DiskImage in GB.
* The actual size is the size the DiskImage actually occupies on storage.
* @return - Actual size used by this DiskImage in GB
*/
public double getActualSize() {
return actualSize;
}
public void setActualSize(double size) {
actualSize = size;
}
public double getActualDiskWithSnapshotsSize() {
if (actualDiskWithSnapthotsSize == 0 && snapshots != null) {
for (DiskImage disk : snapshots) {
actualDiskWithSnapthotsSize += disk.getActualSize();
}
}
return actualDiskWithSnapthotsSize;
}
@JsonIgnore
public double getActualDiskWithSnapshotsSizeInBytes() {
return getActualDiskWithSnapshotsSize() * SizeConverter.BYTES_IN_GB;
}
public Object getQueryableId() {
return getImageId();
}
public ArrayList<DiskImage> getSnapshots() {
return snapshots;
}
public ArrayList<Guid> getQuotaIds() {
return quotaIds;
}
public void setQuotaIds(ArrayList<Guid> quotaIds) {
this.quotaIds = quotaIds;
}
public Guid getQuotaId() {
if (quotaIds == null || quotaIds.isEmpty()) {
return null;
}
return quotaIds.get(0);
}
public void setQuotaId(Guid quotaId) {
quotaIds = new ArrayList<>();
quotaIds.add(quotaId);
}
public ArrayList<String> getQuotaNames() {
return quotaNames;
}
public void setQuotaNames(ArrayList<String> quotaNames) {
this.quotaNames = quotaNames;
}
public String getQuotaName() {
if (quotaNames == null || quotaNames.isEmpty()) {
return null;
}
return quotaNames.get(0);
}
public ArrayList<Guid> getDiskProfileIds() {
return diskProfileIds;
}
public void setDiskProfileIds(ArrayList<Guid> diskProfileIds) {
this.diskProfileIds = diskProfileIds;
}
public ArrayList<String> getDiskProfileNames() {
return diskProfileNames;
}
public void setDiskProfileNames(ArrayList<String> diskProfileNames) {
this.diskProfileNames = diskProfileNames;
}
public Guid getDiskProfileId() {
if (diskProfileIds == null || diskProfileIds.isEmpty()) {
return null;
}
return diskProfileIds.get(0);
}
public void setDiskProfileId(Guid diskProfileId) {
diskProfileIds = new ArrayList<>();
diskProfileIds.add(diskProfileId);
}
public String getDiskProfileName() {
if (diskProfileNames == null || diskProfileNames.isEmpty()) {
return null;
}
return diskProfileNames.get(0);
}
public boolean hasRawBlock() {
if (getVolumeFormat() != VolumeFormat.RAW) {
return false;
}
for (StorageType type : getStorageTypes()) {
if (type.isBlockDomain()) {
return true;
}
}
return false;
}
public static DiskImage copyOf(DiskImage diskImage) {
DiskImage di = new DiskImage();
// set all private fields (imitate clone - deep copy)
di.setVolumeType(diskImage.getVolumeType());
di.setVolumeFormat(diskImage.getVolumeFormat());
di.setSize(diskImage.getSize());
if (diskImage.getQuotaIds() != null) {
di.setQuotaIds(new ArrayList<>(diskImage.getQuotaIds()));
}
if (diskImage.getQuotaNames() != null) {
di.setQuotaNames(new ArrayList<>(diskImage.getQuotaNames()));
}
if (diskImage.getDiskProfileIds() != null) {
di.setDiskProfileIds(new ArrayList<>(diskImage.getDiskProfileIds()));
}
if (diskImage.getDiskProfileNames() != null) {
di.setDiskProfileNames(new ArrayList<>(diskImage.getDiskProfileNames()));
}
di.setQuotaEnforcementType(diskImage.getQuotaEnforcementType());
di.setActive(diskImage.getActive());
di.setCreationDate(new Date(diskImage.getCreationDate().getTime()));
di.setLastModifiedDate(new Date(diskImage.getLastModifiedDate().getTime()));
di.actualSizeInBytes = diskImage.actualSizeInBytes;
di.readRateFromDiskImageDynamic = diskImage.readRateFromDiskImageDynamic;
di.writeRateFromDiskImageDynamic = diskImage.writeRateFromDiskImageDynamic;
di.readLatency = diskImage.readLatency;
di.writeLatency = diskImage.writeLatency;
di.flushLatency = diskImage.flushLatency;
// string is immutable, so no need to deep copy it
di.description = diskImage.description;
di.setImageId(diskImage.getImageId());
di.appList = diskImage.appList;
di.setImageTemplateId(diskImage.getImageTemplateId());
di.setParentId(diskImage.getParentId());
di.setImageStatus(diskImage.getImageStatus());
di.setLastModified(new Date(diskImage.getLastModified().getTime()));
di.storageIds = new ArrayList<>(diskImage.storageIds);
di.setVmSnapshotId(diskImage.getVmSnapshotId());
di.setId(diskImage.getId());
di.setNumberOfVms(diskImage.getNumberOfVms());
di.setWipeAfterDelete(diskImage.isWipeAfterDelete());
di.setPropagateErrors(diskImage.getPropagateErrors());
di.setDiskAlias(diskImage.getDiskAlias());
di.setDiskDescription(diskImage.getDiskDescription());
di.setShareable(diskImage.isShareable());
di.storagePoolId = diskImage.storagePoolId;
di.actualSize = diskImage.actualSize;
// TODO: is it ok to use shallow copy here?!
di.snapshots = new ArrayList<>(diskImage.snapshots);
di.actualDiskWithSnapthotsSize = diskImage.actualDiskWithSnapthotsSize;
di.setCreationDate(new Date());
di.setLastModified(new Date());
di.setActive(true);
di.setImageStatus(ImageStatus.LOCKED);
return di;
}
@Override
public int hashCode() {
return Objects.hash(
super.hashCode(),
getImage(),
snapshots,
actualSizeInBytes,
appList,
description,
readRateFromDiskImageDynamic,
storageIds,
storagePoolId,
storagesNames,
writeRateFromDiskImageDynamic,
readLatency,
writeLatency,
flushLatency,
diskProfileIds,
diskProfileNames
);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof DiskImage)) {
return false;
}
DiskImage other = (DiskImage) obj;
return super.equals(obj)
&& Objects.equals(getImage(), other.getImage())
&& Objects.equals(snapshots, other.snapshots)
&& actualSizeInBytes == other.actualSizeInBytes
&& Objects.equals(appList, other.appList)
&& Objects.equals(description, other.description)
&& readRateFromDiskImageDynamic == other.readRateFromDiskImageDynamic
&& Objects.equals(storageIds, other.storageIds)
&& Objects.equals(storagePoolId, other.storagePoolId)
&& Objects.equals(storagesNames, other.storagesNames)
&& writeRateFromDiskImageDynamic == other.writeRateFromDiskImageDynamic
&& Objects.equals(readLatency, other.readLatency)
&& Objects.equals(writeLatency, other.writeLatency)
&& Objects.equals(flushLatency, other.flushLatency)
&& ObjectUtils.haveSameElements(diskProfileIds, other.diskProfileIds)
&& ObjectUtils.haveSameElements(diskProfileNames, other.diskProfileNames);
}
}