package org.ovirt.engine.core.bll;
import java.util.List;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.businessentities.DiskImage;
import org.ovirt.engine.core.common.businessentities.DiskImageTemplate;
import org.ovirt.engine.core.common.businessentities.ImageStatus;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.businessentities.VMStatus;
import org.ovirt.engine.core.common.businessentities.VmTemplate;
import org.ovirt.engine.core.common.businessentities.image_vm_map;
import org.ovirt.engine.core.common.config.Config;
import org.ovirt.engine.core.common.config.ConfigValues;
import org.ovirt.engine.core.common.errors.VdcBLLException;
import org.ovirt.engine.core.common.vdscommands.GetImageInfoVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.ListImageIdsVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.SetImageLegalityVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.SetVmStatusVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dal.dbbroker.DbFacade;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBase;
import org.ovirt.engine.core.utils.timer.OnTimerMethodAnnotation;
public final class ImagesSyncronizer {
private static final ImagesSyncronizer _imagesSyncronizer = new ImagesSyncronizer();
private static int _imageRefreshRate;
private ImagesSyncronizer() {
_imageRefreshRate = Config.<Integer> GetValue(ConfigValues.ImagesSyncronizationTimeout);
if (_imageRefreshRate != 0) {
// /Should be changed to support current Storage file structure.
// SchedulerUtilQuartzImpl.getInstance().scheduleAFixedDelayJob(this,
// "OnTimer",
// new Class[0], new Object[0],
// 0, _imageRefreshRate,
// TimeUnit.HOURS);
}
}
public static ImagesSyncronizer getInstance() {
return _imagesSyncronizer;
}
@OnTimerMethodAnnotation("OnTimer")
public void OnTimer() {
Syncronize();
}
public void Syncronize() {
/**
* Get All Images from IRS
*/
java.util.ArrayList<Guid> imagesIdsFromIrs = GetImagesFromIrs();
java.util.ArrayList<Guid> inVdcButNotInIrs = new java.util.ArrayList<Guid>();
List<DiskImage> imagesFromVdc = GetImagesFromVdc();
for (DiskImage image : imagesFromVdc) {
if (!imagesIdsFromIrs.contains(image.getId()) && image.getimageStatus() != ImageStatus.ILLEGAL) {
inVdcButNotInIrs.add(image.getId());
} else {
imagesIdsFromIrs.remove(image.getId());
}
}
java.util.ArrayList<Guid> imageIdsFromIrsNotInVdc = new java.util.ArrayList<Guid>();
for (Guid imageId : imagesIdsFromIrs) {
// todo - omer what parameters to send here? and why this code runs
// again?!
DiskImage imageFromIrs = (DiskImage) Backend
.getInstance()
.getResourceManager()
.RunVdsCommand(VDSCommandType.GetImageInfo,
new GetImageInfoVDSCommandParameters(Guid.Empty, Guid.Empty, Guid.Empty, imageId))
.getReturnValue();
if (imageFromIrs.getimageStatus() != ImageStatus.ILLEGAL) {
imageIdsFromIrsNotInVdc.add(imageId);
}
}
/**
* Remove all images, found in Irs and not found in Vdc
*/
ProceedImagesNotFoundInVdc(imageIdsFromIrsNotInVdc);
ProceedImagesNotFoundInIrs(inVdcButNotInIrs);
}
private static java.util.ArrayList<Guid> GetImagesFromIrs() {
// todo - omer review this - not sending any parameters should get all
// volumes
java.util.ArrayList<Guid> imagesIdsFromIrs = new java.util.ArrayList<Guid>(
java.util.Arrays.asList((Guid[]) Backend.getInstance().getResourceManager()
.RunVdsCommand(VDSCommandType.ListImageIds, new ListImageIdsVDSCommandParameters())
.getReturnValue()));
java.util.ArrayList<Guid> toRemoveFromIrs = new java.util.ArrayList<Guid>();
for (Guid imageId : imagesIdsFromIrs) {
// todo - omer what parameters to send here?
DiskImage image = (DiskImage) Backend
.getInstance()
.getResourceManager()
.RunVdsCommand(VDSCommandType.GetImageInfo,
new GetImageInfoVDSCommandParameters(Guid.Empty, Guid.Empty, Guid.Empty, imageId))
.getReturnValue();
if (image.getimageStatus() == ImageStatus.ILLEGAL) {
toRemoveFromIrs.add(imageId);
}
}
for (Guid toRemove : toRemoveFromIrs) {
imagesIdsFromIrs.remove(toRemove);
}
return imagesIdsFromIrs;
}
private static List<DiskImage> GetImagesFromVdc() {
List<DiskImage> imagesFromVdc = DbFacade.getInstance().getDiskImageDAO().getAll();
List<DiskImage> toRemove = new java.util.ArrayList<DiskImage>();
for (DiskImage image : imagesFromVdc) {
if (image.getimageStatus() == ImageStatus.ILLEGAL) {
toRemove.add(image);
}
}
for (DiskImage image : toRemove) {
imagesFromVdc.remove(image);
}
return imagesFromVdc;
}
private static AuditLogType DesktopNotExistInVdcTreatment(Guid imageId, AuditLogableBase logable) {
AuditLogType returnValue;
DiskImageTemplate dt = DbFacade.getInstance().getDiskImageTemplateDAO().get(imageId);
if (dt != null) {
VmTemplate template = DbFacade.getInstance().getVmTemplateDAO()
.get(dt.getvmt_guid());
logable.getCustomValues().put("TemplateName", template.getname());
logable.setVmTemplateId(template.getId());
/**
* Error message: Found Image without vm.
*/
returnValue = AuditLogType.IMAGES_SYNCRONIZER_DESKTOP_NOT_EXIST_IN_VDC;
} else {
returnValue = AuditLogType.IMAGES_SYNCRONIZER_TEMPLATE_NOT_EXIST_IMAGE_EXIST;
/**
* Error. Zombi in Vdc database.
*/
}
return returnValue;
}
private static AuditLogType SnapshotNotExistInVdcTreatment(Guid imageId, AuditLogableBase logable) {
/**
* Vm snapshot
*/
image_vm_map map = DbFacade.getInstance().getImageVmMapDAO().getByImageId(imageId);
AuditLogType returnValue;
if (map != null) {
VM vm = DbFacade.getInstance().getVmDAO().getById(map.getvm_id());
logable.setVmId(vm.getvm_guid());
returnValue = AuditLogType.IMAGES_SYNCRONIZER_SNAPSHOT_NOT_EXIST_IN_VDC;
/**
* Error message: Found VM snapshot not in Vdc.
*/
} else {
returnValue = AuditLogType.IMAGES_SYNCRONIZER_SNAPSHOTS_NOT_ATTACHED_TO_VM_IN_VDC;
/**
* Error. Zombi in Vdc database.
*/
}
return returnValue;
}
private static void ProceedImagesNotFoundInVdc(java.util.ArrayList<Guid> images) {
java.util.HashMap<Guid, Integer> proceeded = new java.util.HashMap<Guid, Integer>();
for (Guid image : images) {
if (!proceeded.containsKey(image)) {
Iterable<DiskImage> snapshots = ImagesHandler.getAllImageSnapshotsFromIrs(image, Guid.Empty);
boolean isFound = false;
AuditLogableBase logable = new AuditLogableBase();
AuditLogType type = AuditLogType.UNASSIGNED;
// todo - omer what parameters to send here?
Backend.getInstance()
.getResourceManager()
.RunVdsCommand(
VDSCommandType.SetImageLegality,
new SetImageLegalityVDSCommandParameters(Guid.Empty, Guid.Empty, Guid.Empty, image,
false));
/**
* TODO: set image illegal in IRS
*/
for (DiskImage diskImage : snapshots) {
logable.AppendCustomValue("SnapshotDescription", diskImage.getdescription(), ",");
if (!proceeded.containsKey(diskImage.getId())) {
proceeded.put(diskImage.getId(), 0);
}
Guid storagePoolId = diskImage.getstorage_pool_id() != null ? diskImage.getstorage_pool_id()
.getValue() : Guid.Empty;
Guid storageDomainId = diskImage.getstorage_id() != null ? diskImage.getstorage_id().getValue()
: Guid.Empty;
Guid imageGroupId = diskImage.getimage_group_id() != null ? diskImage.getimage_group_id()
.getValue() : Guid.Empty;
Backend.getInstance()
.getResourceManager()
.RunVdsCommand(
VDSCommandType.SetImageLegality,
new SetImageLegalityVDSCommandParameters(storagePoolId, storageDomainId,
imageGroupId, diskImage.getId(), false));
/**
* TODO: set image illegal in IRS
*/
DiskImage snapshotFromVdc =
DbFacade.getInstance().getDiskImageDAO().getSnapshotById(diskImage.getId());
if (snapshotFromVdc != null) {
snapshotFromVdc.setimageStatus(ImageStatus.ILLEGAL);
DbFacade.getInstance().getDiskImageDAO().update(snapshotFromVdc);
/**
* Image found in Vdc Db
*/
if (diskImage.getParentId().equals(Guid.Empty)) {
type = DesktopNotExistInVdcTreatment(diskImage.getId(), logable);
} else {
type = SnapshotNotExistInVdcTreatment(diskImage.getId(), logable);
}
isFound = true;
break;
}
}
if (!isFound) {
type = AuditLogType.IMAGES_SYNCRONIZER_TEMPLATE_NOT_EXIST_IN_VDC;
/**
* Error message: found image snapshot not in Vdc. There is
* no data in Vdc.
*/
}
AuditLogDirector.log(logable, type);
if (!proceeded.containsKey(image)) {
proceeded.put(image, 0);
}
}
}
}
private static void ProceedImagesNotFoundInIrs(java.util.ArrayList<Guid> images) {
java.util.ArrayList<image_vm_map> vmImages = new java.util.ArrayList<image_vm_map>();
for (Guid image : images) {
image_vm_map map = DbFacade.getInstance().getImageVmMapDAO().getByImageId(image);
if (map != null) {
vmImages.add(map);
}
}
if (vmImages.size() > 0) {
ProceedVmsNotFoundInIrs(vmImages, images);
}
java.util.ArrayList<DiskImageTemplate> templateImages = new java.util.ArrayList<DiskImageTemplate>();
for (Guid image : images) {
DiskImageTemplate dt = DbFacade.getInstance().getDiskImageTemplateDAO().get(image);
if (dt != null) {
templateImages.add(dt);
}
}
if (templateImages.size() > 0) {
// Not existing template images treatment
for (DiskImageTemplate dt : templateImages) {
DiskImage disk = DbFacade.getInstance().getDiskImageDAO().getSnapshotById(dt.getit_guid());
disk.setimageStatus(ImageStatus.ILLEGAL);
DbFacade.getInstance().getDiskImageDAO().update(disk);
AuditLogableBase logable = new AuditLogableBase();
logable.setVmTemplateId(dt.getvmt_guid());
AuditLogDirector.log(logable, AuditLogType.IMAGES_SYNCRONIZER_IMAGE_TEMPLATE_NOT_EXIST);
}
}
/**
* TODO: do something with images remained.
*/
}
private static void ProceedVmsNotFoundInIrs(Iterable<image_vm_map> vmImages, java.util.Collection<Guid> images) {
boolean isFound = false;
AuditLogableBase logable = new AuditLogableBase();
AuditLogType type = AuditLogType.UNASSIGNED;
for (image_vm_map map : vmImages) {
DiskImage imageFromVdc = DbFacade.getInstance().getDiskImageDAO().get(map.getimage_id());
imageFromVdc.setimageStatus(ImageStatus.ILLEGAL);
DbFacade.getInstance().getDiskImageDAO().update(imageFromVdc);
Backend.getInstance()
.getResourceManager()
.RunVdsCommand(VDSCommandType.SetVmStatus,
new SetVmStatusVDSCommandParameters(map.getvm_id(), VMStatus.ImageIllegal));
logable.setVmId(map.getvm_id());
while (!imageFromVdc.getParentId().equals(Guid.Empty) && !isFound) {
logable.AppendCustomValue("SnapshotDescription", imageFromVdc.getdescription(), ",");
DiskImage parentFromIrs = null;
try {
// todo - omer review if this is right
Guid storagePoolId = imageFromVdc.getstorage_pool_id() != null ? imageFromVdc.getstorage_pool_id()
.getValue() : Guid.Empty;
Guid storageDomainId = imageFromVdc.getstorage_id() != null ? imageFromVdc.getstorage_id()
.getValue() : Guid.Empty;
Guid imageGroupId = imageFromVdc.getimage_group_id() != null ? imageFromVdc.getimage_group_id()
.getValue() : Guid.Empty;
parentFromIrs = (DiskImage) Backend
.getInstance()
.getResourceManager()
.RunVdsCommand(
VDSCommandType.GetImageInfo,
new GetImageInfoVDSCommandParameters(storagePoolId, storageDomainId, imageGroupId,
imageFromVdc.getParentId())).getReturnValue();
}
// catch(IRSErrorImageNotExistException)
catch (VdcBLLException e) {
}
imageFromVdc.setimageStatus(ImageStatus.ILLEGAL);
DbFacade.getInstance().getDiskImageDAO().update(imageFromVdc);
if (parentFromIrs != null) {
isFound = true;
}
imageFromVdc = DbFacade.getInstance().getDiskImageDAO().getSnapshotById(imageFromVdc.getParentId());
images.remove(imageFromVdc.getId());
}
if (isFound) {
/**
* Found snapshot in Irs
*/
if (imageFromVdc.getParentId().equals(Guid.Empty)) {
/**
* Found template
*/
type = AuditLogType.IMAGES_SYNCRONIZER_DESKTOP_NOT_EXIST_IN_IRS;
} else {
/**
* Found vm
*/
type = AuditLogType.IMAGES_SYNCRONIZER_SNAPSHOT_NOT_EXIST_IN_IRS;
}
} else {
/**
* VM without image/Template
*/
type = AuditLogType.IMAGES_SYNCRONIZER_DESKTOP_WITHOUT_TEMPLATE_VDC;
}
}
AuditLogDirector.log(logable, type);
}
}