package org.ovirt.engine.ui.uicommonweb.models.vms;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.ovirt.engine.core.common.businessentities.ArchitectureType;
import org.ovirt.engine.core.common.businessentities.OriginType;
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.network.VmNetworkInterface;
import org.ovirt.engine.core.common.businessentities.network.VnicProfileView;
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.VolumeType;
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.UICommand;
import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider;
import org.ovirt.engine.ui.uicommonweb.models.EntityModel;
import org.ovirt.engine.ui.uicommonweb.models.ListModel;
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.uicompat.ConstantsManager;
import org.ovirt.engine.ui.uicompat.PropertyChangedEventArgs;
import org.ovirt.engine.ui.uicompat.external.StringUtils;
public abstract class ImportVmFromExternalProviderModel extends ImportVmModel {
public static final String ON_DISK_LOAD = "OnDiskLoad"; //$NON-NLS-1$
private Map<Guid, ArrayList<Quota>> storageQuotaMap;
private ListModel<StorageDomain> storage;
private ListModel<VolumeType> allocation;
private final Map<String, ImportDiskData> diskImportDataMap = new HashMap<>();
private final VmImportGeneralModel vmImportGeneralModel;
private VmImportDiskListModel importDiskListModel;
private VmImportInterfaceListModel importInterfaceListModel;
private List<VnicProfileView> networkProfiles;
private ListModel<String> iso;
private EntityModel<Boolean> attachDrivers;
private String winWithoutVirtioMessage;
private boolean sourceIsNotKvm;
protected ImportVmFromExternalProviderModel(VmImportGeneralModel vmImportGeneralModel, VmImportDiskListModel importDiskListModel,
VmImportInterfaceListModel vmImportInterfaceListModel, final ClusterListModel<Void> cluster, final QuotaListModel clusterQuota) {
super(cluster, clusterQuota);
this.vmImportGeneralModel = vmImportGeneralModel;
this.importDiskListModel = importDiskListModel;
this.importInterfaceListModel = vmImportInterfaceListModel;
setStorage(new ListModel<StorageDomain>());
setAllocation(new ListModel<VolumeType>());
getAllocation().setItems(Arrays.asList(VolumeType.Sparse, VolumeType.Preallocated));
sourceIsNotKvm = true;
setIso(new ListModel<String>());
setAttachDrivers(new EntityModel<>(false));
vmImportGeneralModel.getOperatingSystems().getSelectedItemChangedEvent().addListener((ev, sender, args) -> updateWindowsWarningMessage());
getClusterQuota().setIsAvailable(false);
setDetailList(vmImportGeneralModel, vmImportInterfaceListModel, importDiskListModel);
}
private void updateWindowsWarningMessage() {
setWinWithoutVirtioMessage(""); //$NON-NLS-1$
Integer selectedOS = vmImportGeneralModel.getOperatingSystems().getSelectedItem();
if (selectedOS == null) {
return;
}
boolean attachDrivers = getAttachDrivers().getEntity();
boolean someDriverSelected = !StringUtils.isEmpty(getIso().getSelectedItem());
boolean isWindows = AsyncDataProvider.getInstance().isWindowsOsType(selectedOS);
if (isWindows && sourceIsNotKvm && (!attachDrivers || !someDriverSelected)) {
setWinWithoutVirtioMessage(ConstantsManager.getInstance()
.getConstants().missingVirtioDriversForWindows());
}
}
private final Map<String, ImportNetworkData> networkImportDataMap = new HashMap<>();
public List<VnicProfileView> getNetworkProfiles() {
return networkProfiles;
}
public SearchableListModel getImportDiskListModel() {
return importDiskListModel;
}
public SearchableListModel getImportNetworkInterfaceListModel() {
return importInterfaceListModel;
}
@Override
public void init(final List<VM> externalVms, final Guid dataCenterId) {
setCloseCommand(new UICommand(null, this)
.setTitle(ConstantsManager.getInstance().getConstants().close())
.setIsDefault(true)
.setIsCancel(true));
initIsoAndAttachDriversFields(externalVms);
setTargetArchitecture(externalVms);
withDataCenterLoaded(dataCenterId, returnValue -> setItems(r -> doInit(), externalVms));
}
private void initIsoAndAttachDriversFields(final List<VM> externalVms) {
sourceIsNotKvm = externalVms != null && externalVms.size() > 0 && externalVms.get(0).getOrigin() != OriginType.KVM;
getIso().setIsAvailable(sourceIsNotKvm);
getAttachDrivers().setIsAvailable(sourceIsNotKvm);
if (sourceIsNotKvm) {
setAttachDrivers(new EntityModel<>(false));
getIso().setIsChangeable(false);
getAttachDrivers().getEntityChangedEvent().addListener((ev, sender, args) -> {
getIso().setIsChangeable(getAttachDrivers().getEntity());
updateWindowsWarningMessage();
});
getIso().getSelectedItemChangedEvent().addListener((ev, sender, args) -> updateWindowsWarningMessage());
}
}
private void withDataCenterLoaded(Guid dataCenterId, final AsyncCallback<StoragePool> callback) {
AsyncDataProvider.getInstance().getDataCenterById(new AsyncQuery<>(returnValue -> {
setStoragePool(returnValue);
callback.onSuccess(returnValue);
}), dataCenterId);
}
protected void setTargetArchitecture(List<VM> externalVms) {
setTargetArchitecture(externalVms.iterator().next().getClusterArch());
}
protected void doInit() {
final StoragePool dataCenter = getStoragePool();
if (dataCenter == null) {
return;
}
setStoragePool(dataCenter);
getClusterQuota().setIsAvailable(dataCenter.getQuotaEnforcementType() != QuotaEnforcementTypeEnum.DISABLED);
getCluster().getSelectedItemChangedEvent().addListener(clusterChangedListener);
// get cluster
getCluster().setItems(null);
AsyncDataProvider.getInstance().getVnicProfilesByDcId(new AsyncQuery<>(returnValue -> {
networkProfiles = returnValue;
initNetworksList();
initClusterAndStorage(dataCenter);
}), dataCenter.getId());
}
private void initClusterAndStorage(StoragePool dataCenter) {
AsyncDataProvider.getInstance().getClusterByServiceList(new AsyncQuery<>(clusters -> {
ArchitectureType targetArch = getTargetArchitecture();
if (targetArch != null) {
clusters = AsyncDataProvider.getInstance().filterByArchitecture(clusters, targetArch);
}
getCluster().setItems(clusters);
getCluster().setSelectedItem(Linq.firstOrNull(clusters));
// get storage domains
AsyncDataProvider.getInstance().getStorageDomainList(new AsyncQuery<>(
storageDomains -> {
// filter storage domains
List<StorageDomain> filteredStorageDomains = new ArrayList<>();
for (StorageDomain domain : storageDomains) {
if (Linq.isDataActiveStorageDomain(domain)) {
filteredStorageDomains.add(domain);
}
}
getStorage().setItems(filteredStorageDomains);
if (getClusterQuota().getIsAvailable()) {
initQuotaForStorageDomains();
} else {
initDisksStorageDomainsList();
}
}),
getStoragePool().getId());
}),
dataCenter.getId(), true, false);
}
protected void addDiskImportData(String alias,
ArrayList<StorageDomain> storageDomains,
VolumeType volumeType, EntityModel collapseSnapshots) {
ImportDiskData data = new ImportDiskData();
data.setCollapseSnapshot(collapseSnapshots);
data.setAllStorageDomains(new ArrayList<StorageDomain>());
data.setStorageDomains(storageDomains);
data.setVolumeType(volumeType);
data.setStorageQuotaList(storageQuotaMap);
diskImportDataMap.put(alias, data);
}
protected void addNetworkImportData(VmNetworkInterface iface) {
networkImportDataMap.put(
iface.getVmName() + "$" + iface.getName(), //$NON-NLS-1$
new ImportNetworkData(networkProfiles));
}
protected void initNetworksList() {
for (Object item : getItems()) {
ImportVmData importVmData = (ImportVmData) item;
VM vm = importVmData.getVm();
for (VmNetworkInterface iface : vm.getInterfaces()) {
addNetworkImportData(iface);
}
}
}
protected void initDisksStorageDomainsList() {
for (Object item : getItems()) {
ImportVmData importVmData = (ImportVmData) item;
VM vm = importVmData.getVm();
for (Disk disk : vm.getDiskMap().values()) {
DiskImage diskImage = (DiskImage) disk;
addDiskImportData(
diskImage.getDiskAlias(),
new ArrayList<StorageDomain>(),
diskImage.getVolumeType(),
importVmData.getCollapseSnapshots());
}
}
initIsoImages();
postInitDisks();
}
private void postInitDisks() {
stopProgress();
}
private void initIsoImages() {
AsyncDataProvider.getInstance().getIrsImageList(new AsyncQuery<>(
images -> {
getIso().setItems(images);
getIso().setSelectedItem(tryToFindVirtioTools(images));
}),
getStoragePool().getId(),
false);
}
private String tryToFindVirtioTools(List<String> isos) {
for (String iso : isos) {
if (iso.startsWith("virtio-win")) { //$NON-NLS-1$
return iso;
}
}
return isos.isEmpty() ? null : isos.get(0);
}
private void initQuotaForStorageDomains() {
List<VdcQueryType> queryTypeList = new ArrayList<>();
List<VdcQueryParametersBase> queryParamsList = new ArrayList<>();
for (StorageDomain storage : getStorage().getItems()) {
queryTypeList.add(VdcQueryType.GetAllRelevantQuotasForStorage);
queryParamsList.add(new IdQueryParameters(storage.getId()));
}
storageQuotaMap = new HashMap<>();
Frontend.getInstance().runMultipleQueries(queryTypeList,
queryParamsList,
result -> {
Iterator<VdcQueryReturnValue> returnValuesIter = result.getReturnValues().iterator();
Iterator<StorageDomain> domainsIter = getStorage().getItems().iterator();
boolean noQuota = true;
while(domainsIter.hasNext()) {
ArrayList<Quota> quotaList = returnValuesIter.next().getReturnValue();
noQuota = noQuota && quotaList.isEmpty();
storageQuotaMap.put(
domainsIter.next().getId(),
quotaList);
}
if (noQuota
&& QuotaEnforcementTypeEnum.HARD_ENFORCEMENT.equals(storagePool.getQuotaEnforcementType())) {
showCloseMessage(ConstantsManager.getInstance()
.getConstants().missingQuotaStorageEnforceMode());
}
initDisksStorageDomainsList();
});
}
@Override
protected String getListName() {
return "ImportVmFromExternalProviderModel"; //$NON-NLS-1$
}
public ListModel<StorageDomain> getStorage() {
return storage;
}
public void setStorage(ListModel<StorageDomain> storage) {
this.storage = storage;
}
public ListModel<VolumeType> getAllocation() {
return allocation;
}
public void setAllocation(ListModel<VolumeType> allocation) {
this.allocation = allocation;
}
public ImportDiskData getDiskImportData(String alias) {
ImportDiskData importData = diskImportDataMap.get(alias);
if (importData != null) {
if (storage.getSelectedItem() == null) {
importData.setSelectedStorageDomain(storage.getSelectedItem());
}
}
return importData;
}
public ImportNetworkData getNetworkImportData(VmNetworkInterface iface) {
return networkImportDataMap.get(iface.getVmName() + "$" + iface.getName()); //$NON-NLS-1$
}
@Override
public boolean validate() {
return true;
}
public ListModel<String> getIso() {
return iso;
}
public void setIso(ListModel<String> iso) {
this.iso = iso;
}
public EntityModel<Boolean> getAttachDrivers() {
return attachDrivers;
}
public void setAttachDrivers(EntityModel<Boolean> attachTools) {
this.attachDrivers = attachTools;
}
protected void updateNetworkInterfacesForVm(VM vm) {
for (VmNetworkInterface iface : vm.getInterfaces()) {
ImportNetworkData importNetworkData = getNetworkImportData(iface);
VnicProfileView profile = importNetworkData.getSelectedNetworkProfile();
if (profile != null) {
iface.setNetworkName(profile.getNetworkName());
iface.setVnicProfileName(profile.getName());
}
}
}
public String getWinWithoutVirtioMessage() {
return winWithoutVirtioMessage;
}
public void setWinWithoutVirtioMessage(String value) {
if (!Objects.equals(winWithoutVirtioMessage, value)) {
winWithoutVirtioMessage = value;
onPropertyChanged(new PropertyChangedEventArgs("WinWithoutVirtioMessage")); //$NON-NLS-1$
}
}
}