package org.ovirt.engine.ui.uicommonweb.models.vms;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.ovirt.engine.core.common.action.ImportVmParameters;
import org.ovirt.engine.core.common.action.VdcActionParametersBase;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.businessentities.ArchitectureType;
import org.ovirt.engine.core.common.businessentities.Cluster;
import org.ovirt.engine.core.common.businessentities.Quota;
import org.ovirt.engine.core.common.businessentities.QuotaEnforcementTypeEnum;
import org.ovirt.engine.core.common.businessentities.StorageDomain;
import org.ovirt.engine.core.common.businessentities.StoragePool;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.businessentities.VmTemplate;
import org.ovirt.engine.core.common.businessentities.profiles.CpuProfile;
import org.ovirt.engine.core.common.businessentities.storage.Disk;
import org.ovirt.engine.core.common.businessentities.storage.DiskImage;
import org.ovirt.engine.core.common.businessentities.storage.VolumeFormat;
import org.ovirt.engine.core.common.businessentities.storage.VolumeType;
import org.ovirt.engine.core.common.queries.GetAllFromExportDomainQueryParameters;
import org.ovirt.engine.core.common.queries.IdQueryParameters;
import org.ovirt.engine.core.common.queries.VdcQueryParametersBase;
import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.ui.frontend.AsyncCallback;
import org.ovirt.engine.ui.frontend.Frontend;
import org.ovirt.engine.ui.uicommonweb.Linq;
import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider;
import org.ovirt.engine.ui.uicommonweb.models.EntityModel;
import org.ovirt.engine.ui.uicommonweb.models.SearchableListModel;
import org.ovirt.engine.ui.uicommonweb.models.clusters.ClusterListModel;
import org.ovirt.engine.ui.uicommonweb.models.quota.QuotaListModel;
import org.ovirt.engine.ui.uicommonweb.validation.IValidation;
import org.ovirt.engine.ui.uicommonweb.validation.NotEmptyValidation;
import org.ovirt.engine.ui.uicompat.ConstantsManager;
import org.ovirt.engine.ui.uicompat.IFrontendMultipleActionAsyncCallback;
import org.ovirt.engine.ui.uicompat.PropertyChangedEventArgs;
import com.google.inject.Inject;
public class ImportVmFromExportDomainModel extends ImportVmModel {
public static final String ON_DISK_LOAD = "OnDiskLoad"; //$NON-NLS-1$
private final VmImportDiskListModel importDiskListModel;
private final Map<Guid, List<Disk>> missingTemplateDiskMap = new HashMap<>();
protected ArrayList<StorageDomain> filteredStorageDomains;
private Map<Guid, ArrayList<Quota>> storageQuotaMap;
private final Map<Guid, List<Disk>> templateDiskMap = new HashMap<>();
private final Map<Guid, ImportDiskData> diskImportDataMap = new HashMap<>();
@Override
public void setSelectedItem(Object value) {
super.setSelectedItem(value);
onEntityChanged();
}
@Inject
public ImportVmFromExportDomainModel(final VmImportDiskListModel vmImportDiskListModel,
final ClusterListModel<Void> cluster, final QuotaListModel clusterQuota,
final VmImportGeneralModel vmImportGeneralModel, final VmImportInterfaceListModel vmImportInterfaceListModel,
final VmImportAppListModel vmImportAppListModel) {
super(cluster, clusterQuota);
importDiskListModel = vmImportDiskListModel;
setDetailList(vmImportGeneralModel, vmImportInterfaceListModel, importDiskListModel, vmImportAppListModel);
}
protected void doInit() {
StoragePool dataCenter = getStoragePool();
if (dataCenter == null) {
return;
}
getClusterQuota().setIsAvailable(dataCenter.getQuotaEnforcementType() != QuotaEnforcementTypeEnum.DISABLED);
getCluster().getSelectedItemChangedEvent().addListener(clusterChangedListener);
// get cluster
getCluster().setItems(null);
AsyncDataProvider.getInstance().getClusterByServiceList(new AsyncQuery<>(clusters -> {
ArchitectureType targetArch = getTargetArchitecture();
if (targetArch != null) {
List<Cluster> filteredClusters = AsyncDataProvider.getInstance().filterByArchitecture(clusters,
targetArch);
getCluster().setItems(filteredClusters);
getCluster().setSelectedItem(Linq.firstOrNull(filteredClusters));
} else {
getCluster().setItems(clusters);
getCluster().setSelectedItem(Linq.firstOrNull(clusters));
}
// get storage domains
AsyncDataProvider.getInstance().getStorageDomainList(new AsyncQuery<>(
storageDomains -> {
// filter storage domains
filteredStorageDomains = new ArrayList<>();
for (StorageDomain domain : storageDomains) {
if (Linq.isDataActiveStorageDomain(domain)) {
filteredStorageDomains.add(domain);
}
}
if (getClusterQuota().getIsAvailable()) {
initQuotaForStorageDomains();
} else {
initDisksStorageDomainsList();
}
}),
getStoragePool().getId());
}), dataCenter.getId(), true, false);
}
private void initQuotaForStorageDomains() {
ArrayList<VdcQueryType> queryTypeList = new ArrayList<>();
ArrayList<VdcQueryParametersBase> queryParamsList =
new ArrayList<>();
for (StorageDomain storage : filteredStorageDomains) {
queryTypeList.add(VdcQueryType.GetAllRelevantQuotasForStorage);
queryParamsList.add(new IdQueryParameters(storage.getId()));
}
storageQuotaMap = new HashMap<>();
Frontend.getInstance().runMultipleQueries(queryTypeList,
queryParamsList,
result -> {
List<VdcQueryReturnValue> returnValueList =
result.getReturnValues();
boolean noQuota = true;
for (int i = 0; i < filteredStorageDomains.size(); i++) {
ArrayList<Quota> quotaList = returnValueList.get(i)
.getReturnValue();
if (noQuota
&& !quotaList.isEmpty()) {
noQuota = false;
}
storageQuotaMap.put(
filteredStorageDomains.get(i).getId(),
quotaList);
}
if (noQuota
&& QuotaEnforcementTypeEnum.HARD_ENFORCEMENT.equals(storagePool.getQuotaEnforcementType())) {
showCloseMessage(ConstantsManager.getInstance()
.getConstants()
.missingQuotaStorageEnforceMode());
}
initDisksStorageDomainsList();
});
}
protected void checkDestFormatCompatibility() {
for (Object item : getItems()) {
VM vm = ((ImportVmData) item).getVm();
if (vm.getDiskMap() != null) {
for (Map.Entry<Guid, Disk> pair : vm.getDiskMap().entrySet()) {
DiskImage disk = (DiskImage) pair.getValue();
if (disk.getVolumeType() == VolumeType.Sparse
&& disk.getVolumeFormat() == VolumeFormat.RAW
&& getDiskImportData(disk.getId()) != null
&& getDiskImportData(disk.getId()).getSelectedStorageDomain()
.getStorageType().isBlockDomain()) {
((ImportVmData) item).setWarning(ConstantsManager.getInstance().getConstants()
.importSparseDiskToBlockDeviceMustCollapseSnapshots());
((ImportVmData) item).getCollapseSnapshots().setEntity(true);
((ImportVmData) item).getCollapseSnapshots()
.setChangeProhibitionReason(ConstantsManager.getInstance()
.getConstants()
.importSparseDiskToBlockDeviceMustCollapseSnapshots());
((ImportVmData) item).getCollapseSnapshots().setIsChangeable(false);
onPropertyChanged(new PropertyChangedEventArgs(ON_DISK_LOAD));
}
}
}
}
}
protected void initDisksStorageDomainsList() {
for (Object item : getItems()) {
ImportVmData importVmData = (ImportVmData) item;
VM vm = importVmData.getVm();
if (!Guid.Empty.equals(vm.getVmtGuid())) {
if (!templateDiskMap.containsKey(vm.getVmtGuid())) {
templateDiskMap.put(vm.getVmtGuid(), new ArrayList<Disk>());
}
templateDiskMap.get(vm.getVmtGuid()).addAll(extractRootDisks(vm));
}
for (Disk disk : vm.getDiskMap().values()) {
DiskImage diskImage = (DiskImage) disk;
addDiskImportData(diskImage.getId(),
filteredStorageDomains,
diskImage.getVolumeType(),
importVmData.getCollapseSnapshots());
}
}
if (!templateDiskMap.isEmpty()) {
ArrayList<VdcQueryType> queryTypeList = new ArrayList<>();
final ArrayList<VdcQueryParametersBase> queryParamsList = new ArrayList<>();
for (Guid templateId : templateDiskMap.keySet()) {
queryTypeList.add(VdcQueryType.GetVmTemplatesDisks);
queryParamsList.add(new IdQueryParameters(templateId));
}
Frontend.getInstance().runMultipleQueries(queryTypeList, queryParamsList, result -> {
List<VdcQueryReturnValue> returnValueList = result.getReturnValues();
Map<Guid, ArrayList<StorageDomain>> templateDisksStorageDomains =
new HashMap<>();
for (VdcQueryReturnValue returnValue : returnValueList) {
for (DiskImage diskImage : (ArrayList<DiskImage>) returnValue.getReturnValue()) {
templateDisksStorageDomains.put(diskImage.getImageId(),
getStorageDomainsByIds(diskImage.getStorageIds()));
}
}
for (Entry<Guid, List<Disk>> guidListEntry : templateDiskMap.entrySet()) {
for (Disk disk : guidListEntry.getValue()) {
DiskImage diskImage = (DiskImage) disk;
if (diskImage.getParentId() != null && !Guid.Empty.equals(diskImage.getParentId())) {
ArrayList<StorageDomain> storageDomains =
templateDisksStorageDomains.get(diskImage.getParentId());
if (storageDomains == null) {
missingTemplateDiskMap.put(guidListEntry.getKey(), guidListEntry.getValue());
}
}
}
}
if (!missingTemplateDiskMap.keySet().isEmpty()) {
getTemplatesFromExportDomain();
} else {
postInitDisks();
}
});
} else {
postInitDisks();
}
}
private Collection<Disk> extractRootDisks(VM vm) {
Set<Disk> rootDisks = new HashSet<>();
for (DiskImage candidate : vm.getImages()) {
if (isRoot(candidate, vm.getImages())) {
rootDisks.add(candidate);
}
}
return rootDisks;
}
private boolean isRoot(DiskImage candidate, List<DiskImage> images) {
for (DiskImage image : images) {
if (candidate.getParentId().equals(image.getImageId())) {
// if the candidate has a parent then it is not a root
return false;
}
}
// if we did not find a parent of a candidate then it is a root
return true;
}
protected void getTemplatesFromExportDomain() {
GetAllFromExportDomainQueryParameters tempVar =
new GetAllFromExportDomainQueryParameters(storagePool.getId(), (Guid) getEntity());
Frontend.getInstance().runQuery(VdcQueryType.GetTemplatesFromExportDomain, tempVar,
new AsyncQuery<VdcQueryReturnValue>(returnValue -> {
Map<VmTemplate, List<DiskImage>> dictionary = (HashMap<VmTemplate, List<DiskImage>>) returnValue.getReturnValue();
Map<Guid, Guid> tempMap = new HashMap<>();
for (Entry<VmTemplate, List<DiskImage>> entry : dictionary.entrySet()) {
tempMap.put(entry.getKey().getId(), null);
}
for (Entry<Guid, List<Disk>> missingTemplateEntry : missingTemplateDiskMap.entrySet()) {
if (tempMap.containsKey(missingTemplateEntry.getKey())) {
for (Disk disk : missingTemplateEntry.getValue()) {
addDiskImportData(disk.getId(),
filteredStorageDomains,
((DiskImage) disk).getVolumeType(),
new EntityModel(true));
}
} else {
showCloseMessage(ConstantsManager.getInstance()
.getConstants()
.errorTemplateCannotBeFoundMessage());
return;
}
}
ImportVmFromExportDomainModel.this.setMessage(ConstantsManager.getInstance()
.getConstants()
.importMissingStorages());
for (ImportVmData vmData : (List<ImportVmData>) getItems()) {
if (!Guid.Empty.equals(vmData.getVm().getVmtGuid())
&& missingTemplateDiskMap.containsKey(vmData.getVm().getVmtGuid())) {
vmData.setTemplateExistsInSetup(false);
}
}
postInitDisks();
}));
}
protected void postInitDisks() {
onDataLoad();
checkDestFormatCompatibility();
stopProgress();
}
public void onDataLoad() {
onPropertyChanged(new PropertyChangedEventArgs(ON_DISK_LOAD));
}
private ArrayList<StorageDomain> getStorageDomainsByIds(ArrayList<Guid> getstorage_ids) {
ArrayList<StorageDomain> domains = new ArrayList<>();
for (Guid storageDomainId : getstorage_ids) {
for (StorageDomain storageDomain : filteredStorageDomains) {
if (storageDomainId.equals(storageDomain.getId())) {
domains.add(storageDomain);
break;
}
}
}
return domains;
}
public ImportDiskData getDiskImportData(Guid diskId) {
return diskImportDataMap.get(diskId);
}
protected void addDiskImportData(Guid diskId,
ArrayList<StorageDomain> storageDomains,
VolumeType volumeType, EntityModel collapseSnapshots) {
ImportDiskData data = new ImportDiskData();
data.setCollapseSnapshot(collapseSnapshots);
data.setAllStorageDomains(filteredStorageDomains);
data.setStorageDomains(storageDomains);
data.setVolumeType(volumeType);
data.setStorageQuotaList(storageQuotaMap);
diskImportDataMap.put(diskId, data);
}
@Override
protected void activeDetailModelChanged() {
super.activeDetailModelChanged();
}
public boolean validate() {
if (QuotaEnforcementTypeEnum.HARD_ENFORCEMENT.equals(storagePool.getQuotaEnforcementType())) {
getClusterQuota().validateSelectedItem(
new IValidation[] { new NotEmptyValidation() });
for (ImportDiskData item : diskImportDataMap.values()) {
if (item.getSelectedQuota() == null) {
setMessage(ConstantsManager.getInstance().getConstants().missingQuotaStorageEnforceMode());
return false;
}
}
if (getMessage() != null
&& getMessage().equals(ConstantsManager.getInstance()
.getConstants()
.missingQuotaStorageEnforceMode())) {
setMessage("");
}
}
getCluster().validateSelectedItem(
new IValidation[] { new NotEmptyValidation() });
return validateNames()
&& getCluster().getIsValid()
&& getClusterQuota().getIsValid();
}
protected void withDataCenterLoaded(Guid storageDomainId, final AsyncCallback<List<StoragePool>> callback) {
// get Storage pool
AsyncDataProvider.getInstance().getDataCentersByStorageDomain(new AsyncQuery<>(pools -> {
if (pools == null || pools.size() != 1) {
return;
}
StoragePool dataCenter = pools.get(0);
setStoragePool(dataCenter);
callback.onSuccess(pools);
}), storageDomainId);
}
public void init(final List<VM> externalVms, final Guid storageDomainId) {
withDataCenterLoaded(storageDomainId, returnValue -> setItems(r -> doInit(), externalVms));
}
@Override
protected String getListName() {
return "ImportVmModel"; //$NON-NLS-1$
}
public SearchableListModel getImportDiskListModel() {
return importDiskListModel;
}
public boolean isQuotaEnabled() {
return getStoragePool() != null
&& getStoragePool().getQuotaEnforcementType() != QuotaEnforcementTypeEnum.DISABLED;
}
public void importVms(IFrontendMultipleActionAsyncCallback callback) {
startProgress();
Frontend.getInstance().runMultipleAction(
VdcActionType.ImportVm,
buildImportVmParameters(),
callback,
this);
}
private List<VdcActionParametersBase> buildImportVmParameters() {
List<VdcActionParametersBase> prms = new ArrayList<>();
for (Object item : getItems()) {
VM vm = ((ImportVmData) item).getVm();
ImportVmParameters prm = new ImportVmParameters(vm, (Guid) getEntity(),
Guid.Empty, getStoragePool().getId(),
getCluster().getSelectedItem().getId());
if (getClusterQuota().getSelectedItem() != null &&
getClusterQuota().getIsAvailable()) {
prm.setQuotaId(getClusterQuota().getSelectedItem().getId());
}
CpuProfile cpuProfile = getCpuProfiles().getSelectedItem();
if (cpuProfile != null) {
prm.setCpuProfileId(cpuProfile.getId());
}
prm.setForceOverride(true);
prm.setCopyCollapse(((ImportVmData) item).getCollapseSnapshots().getEntity());
Map<Guid, Guid> map = new HashMap<>();
for (Map.Entry<Guid, Disk> entry : vm.getDiskMap().entrySet()) {
DiskImage disk = (DiskImage) entry.getValue();
map.put(disk.getId(), getDiskImportData(disk.getId()).getSelectedStorageDomain().getId());
disk.setVolumeFormat(
AsyncDataProvider.getInstance().getDiskVolumeFormat(
getDiskImportData(disk.getId()).getSelectedVolumeType(),
getDiskImportData(
disk.getId()).getSelectedStorageDomain().getStorageType()));
disk.setVolumeType(getDiskImportData(disk.getId()).getSelectedVolumeType());
if (getDiskImportData(disk.getId()).getSelectedQuota() != null) {
disk.setQuotaId(
getDiskImportData(disk.getId()).getSelectedQuota().getId());
}
}
prm.setImageToDestinationDomainMap(map);
if (((ImportVmData) item).isExistsInSystem() ||
((ImportVmData) item).getClone().getEntity()) {
prm.setImportAsNewEntity(true);
prm.setCopyCollapse(true);
}
prms.add(prm);
}
return prms;
}
}